Docker Compose for Production: Patterns That Actually Work

Docker Compose isn’t just for development. With the right patterns, it’s a legitimate production deployment tool for small-to-medium workloads. Here’s how to do it without the footguns. Base Structure 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # docker-compose.yml version: "3.8" services: app: image: myapp:${VERSION:-latest} restart: unless-stopped environment: - NODE_ENV=production deploy: resources: limits: cpus: '2' memory: 1G healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s Key elements: ...

March 12, 2026 Β· 7 min Β· 1321 words Β· Rob Washington

Docker Compose Patterns for Production

Docker Compose is often dismissed as β€œjust for development,” but with the right patterns it handles production workloads well. Here are patterns that have survived contact with real systems. Service Dependencies Done Right The basic depends_on only waits for the container to start, not for the service to be ready: 1 2 3 4 5 6 7 # This doesn't guarantee postgres is accepting connections services: app: depends_on: - db db: image: postgres:15 Use health checks for real dependency management: ...

March 5, 2026 Β· 4 min Β· 832 words Β· Rob Washington

Docker Compose Patterns for Local Development

Docker Compose turns β€œworks on my machine” into β€œworks everywhere.” Here’s how to structure it for real development workflows. Basic Structure 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # docker-compose.yml services: app: build: . ports: - "3000:3000" volumes: - .:/app environment: - NODE_ENV=development db: image: postgres:15 environment: POSTGRES_PASSWORD: devpass Start everything: ...

February 28, 2026 Β· 6 min Β· 1088 words Β· Rob Washington

Docker Compose for Production: Beyond the Tutorial

Docker Compose tutorials show you docker compose up. Production requires health checks, resource limits, proper logging, restart policies, and deployment strategies. Here’s how to bridge that gap. Base Configuration 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # docker-compose.yml version: "3.8" services: app: image: myapp:${VERSION:-latest} build: context: . dockerfile: Dockerfile restart: unless-stopped environment: - NODE_ENV=production env_file: - .env ports: - "3000:3000" This is a starting point. Let’s make it production-ready. ...

February 26, 2026 Β· 6 min Β· 1214 words Β· Rob Washington

Docker Compose Patterns for Production-Ready Services

Docker Compose bridges the gap between single-container development and full orchestration. These patterns will help you build maintainable, production-ready configurations. Project Structure m β”œ β”œ β”œ β”œ β”œ β”œ β”” y ─ ─ ─ ─ ─ ─ ─ p ─ ─ ─ ─ ─ ─ ─ r o d d d d . . s β”œ β”‚ β”œ β”‚ β”” j o o o o e e e ─ ─ ─ e c c c c n n r ─ ─ ─ c k k k k v v v t e e e e . i a β”” w β”” n β”œ β”” / r r r r e c p ─ o ─ g ─ ─ - - - - x e p ─ r ─ i ─ ─ c c c c a s k n o o o o m D e D x D n m m m m p o r / o g p p p p l c c c i o o o o e k k k n s s s s e e e x e e e e r r r . . . . . f f f c y o p t i i i o m v r e l l l n l e o s e e e f r d t r . . i y y d m m e l l . y m l # # # # # # B D P T E T a e r e n e s v o s v m e d t i p u r l c v c c o a o e t o n t n r i n m e f r o f e i i n i n ( g d g t c u e u o r s v r v m a e a a m t ( r t r i i a r i i t o u i o a t n t d n b e o e l d - s e ) l s o a d e d ) Base Configuration 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 # docker-compose.yml version: "3.8" services: app: build: context: ./services/app dockerfile: Dockerfile environment: - DATABASE_URL=${DATABASE_URL} - REDIS_URL=${REDIS_URL} depends_on: db: condition: service_healthy redis: condition: service_started networks: - backend restart: unless-stopped db: image: postgres:15-alpine environment: POSTGRES_DB: ${DB_NAME} POSTGRES_USER: ${DB_USER} POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"] interval: 10s timeout: 5s retries: 5 networks: - backend redis: image: redis:7-alpine volumes: - redis_data:/data networks: - backend networks: backend: driver: bridge volumes: postgres_data: redis_data: Development Overrides 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # docker-compose.override.yml (auto-loaded with docker-compose up) version: "3.8" services: app: build: target: development volumes: - ./src:/app/src:cached - /app/node_modules ports: - "3000:3000" - "9229:9229" # Debugger environment: - DEBUG=true - LOG_LEVEL=debug command: npm run dev db: ports: - "5432:5432" redis: ports: - "6379:6379" Production Configuration 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 # docker-compose.prod.yml version: "3.8" services: app: build: target: production deploy: replicas: 3 resources: limits: cpus: '1' memory: 512M reservations: cpus: '0.5' memory: 256M restart_policy: condition: on-failure delay: 5s max_attempts: 3 environment: - NODE_ENV=production - LOG_LEVEL=info logging: driver: json-file options: max-size: "10m" max-file: "3" nginx: image: nginx:alpine ports: - "80:80" - "443:443" volumes: - ./services/nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./certs:/etc/nginx/certs:ro depends_on: - app networks: - backend - frontend networks: frontend: driver: bridge Run with: ...

February 25, 2026 Β· 8 min Β· 1514 words Β· Rob Washington