| name | docker-compose |
| description | Docker Compose for local dev: multi-service stacks, volumes, networking, health checks, env vars, production-like local environments |
Docker Compose Skill
When to activate
- Setting up a local dev environment with multiple services (app + DB + Redis + etc.)
- Writing or debugging a
docker-compose.yml or compose.yaml
- Making local services match production (same DB version, same env vars)
- Adding health checks, depends_on ordering, or volume mounts
- Running integration tests against real services locally
When NOT to use
- Production deployments — use Kubernetes, ECS, or Fly.io
- Single-container apps — use
docker run directly
- CI/CD pipeline service containers — use native CI service definitions
Instructions
Standard dev stack compose file
name: myapp
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
target: dev
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
NODE_ENV: development
DATABASE_URL: postgresql://postgres:postgres@db:5432/myapp
REDIS_URL: redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
develop:
watch:
- action: sync
path: ./src
target: /app/src
db:
image: postgres:16-alpine
ports:
- "5432:5432"
environment:
POSTGRES_DB: myapp
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d myapp"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
command: redis-server --appendonly yes
mailpit:
image: axllent/mailpit
ports:
- "8025:8025"
- "1025:1025"
environment:
SMTP_AUTH_ACCEPT_ANY: true
volumes:
postgres_data:
redis_data:
Commands
docker compose up -d
docker compose up
docker compose up -d --build
docker compose stop
docker compose down
docker compose down -v
docker compose logs -f
docker compose logs -f app
docker compose exec app bash
docker compose exec db psql -U postgres myapp
docker compose run --rm app npm run migrate
docker compose up -d --scale worker=3
Environment variable management
services:
app:
environment:
NODE_ENV: development
env_file:
- .env
- .env.local
environment:
API_KEY: ${API_KEY}
DATABASE_URL=postgresql://postgres:postgres@db:5432/myapp
REDIS_URL=redis://redis:6379
NODE_ENV=development
API_KEY=sk-real-key
STRIPE_SECRET_KEY=sk_test_xxx
Service networking
Services on the same Compose project communicate using service names as hostnames:
services:
app:
environment:
DATABASE_URL: postgresql://postgres:postgres@db:5432/myapp
db:
image: postgres:16-alpine
services:
frontend:
networks: [public, internal]
api:
networks: [internal]
db:
networks: [internal]
networks:
public:
internal:
internal: true
Multi-stage Dockerfile for dev/prod parity
# Dockerfile
FROM node:22-alpine AS base
WORKDIR /app
COPY package*.json ./
# Development stage — includes devDependencies, hot reload
FROM base AS dev
RUN npm install
COPY . .
CMD ["npm", "run", "dev"]
# Build stage
FROM base AS build
RUN npm ci
COPY . .
RUN npm run build
# Production stage — minimal image
FROM node:22-alpine AS prod
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/main.js"]
services:
app:
build:
context: .
target: dev
services:
app:
build:
context: .
target: prod
Health checks and startup ordering
services:
app:
depends_on:
db:
condition: service_healthy
migrate:
condition: service_completed_successfully
db:
image: postgres:16-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 10
start_period: 10s
migrate:
build: .
command: npm run migrate
depends_on:
db:
condition: service_healthy
restart: "no"
Useful patterns
Profile-based optional services:
services:
app:
image: myapp
pgadmin:
image: dpage/pgadmin4
profiles: [tools]
ports:
- "5050:80"
environment:
PGADMIN_DEFAULT_EMAIL: admin@example.com
PGADMIN_DEFAULT_PASSWORD: admin
Bind mount for config files:
services:
nginx:
image: nginx:alpine
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
ports:
- "80:80"
Running DB migrations on start:
services:
app:
command: >
sh -c "npm run migrate && npm run dev"
depends_on:
db:
condition: service_healthy
Example
User: Set up a local dev environment for a FastAPI app with PostgreSQL, Redis, Celery worker, and a React frontend — all matching production configuration.
Expected output:
services:
api:
worker:
frontend:
db:
redis:
flower: