RSSAmplifier

eshlox · Apr 7, 2026

Docker-first development architecture

0
Sign in to vote or save

Przemysław Kołodziejczyk · eshlox

Software developer · since 2002

TLDR: Run your API and database in Docker Compose. Inject secrets with infisical run -- docker compose up. Run AI agents in a separate sandbox with only source code. No .env files on disk. Secrets exist only in container memory. AI cannot see them.


Your dev stack needs secrets. Your AI agent needs your codebase. These two must never share the same environment.

HOST MACHINE

├── Docker Compose (dev stack)

│ ├── API container (secrets via Infisical)

│ ├── PostgreSQL, Redis

│ └── Frontend (public vars only)

├── AI Sandbox (Claude Code / Codex)

│ ├── Source code (mounted)

│ └── NO secrets, NO env vars

├── Infisical CLI (fetches secrets, injects into Docker)

└── 1Password (personal passwords, SSH keys, 2FA)

docker-compose.dev.yml

services:

api:

build: { context: ., dockerfile: Dockerfile.dev }

volumes: [./apps/api/src:/app/apps/api/src]

ports: ["3333:3333"]

environment:

- DATABASE_URL # No value = inherited from host

- DATABASE_PASSWORD # Infisical populates these

- STRIPE_SECRET_KEY

- JWT_SECRET

depends_on: [postgres, redis]

web:

build: { context: ., dockerfile: Dockerfile.dev }

volumes: [./apps/web/src:/app/apps/web/src]

ports: ["3000:3000"]

environment:

- NEXT_PUBLIC_API_URL=http://localhost:3333

postgres:

image: postgres:16-alpine

environment:

{

POSTGRES_DB: myapp_dev,

POSTGRES_USER: myapp,

POSTGRES_PASSWORD: dev-password,

}

# No host ports. Only reachable by other containers on the same network.

redis:

image: redis:7-alpine

# No host ports. Only reachable by other containers on the same network.

Starting the stack

# Infrastructure first

docker compose -f docker-compose.dev.yml up -d postgres redis

# API with secrets injected

infisical run --env=dev -- docker compose -f docker-compose.dev.yml up -d api

# Frontend (no secrets needed)

docker compose -f docker-compose.dev.yml up -d web

Infisical fetches secrets and injects them as env vars. Docker Compose passes them to the container. Nothing touches disk. See Setting up Infisical for the setup.

Common tasks

# Logs

docker compose -f docker-compose.dev.yml logs -f api

# Migrations

infisical run --env=dev -- docker compose -f docker-compose.dev.yml exec api node ace migration:run

# Tests

infisical run --env=dev -- docker compose -f docker-compose.dev.yml exec api npm test

# Rebuild

infisical run --env=dev -- docker compose -f docker-compose.dev.yml up -d --build api

# Restart after secret rotation

infisical run --env=dev -- docker compose -f docker-compose.dev.yml restart api

The .env.example file

Document which env vars exist. Commit to git with placeholder values. Real .env files must never exist.

DATABASE_URL=postgresql://localhost:5432/myapp_dev

STRIPE_SECRET_KEY=sk_test_replace_me

JWT_SECRET=replace-me


Spot something wrong?

Found a typo, a broken link, or something that could be better? I would love to hear from you. Drop me a message and I will fix it.

Read the original on eshlox.net

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.