Docker Compose Production Patterns
Layer a base compose file with an override for production, set resource limits, restart policies and healthcheck-aware dependencies.
Compose is not just for local dev. With a few patterns it runs small production stacks cleanly. The core idea is one base file plus environment-specific overrides.
Base + override files
Keep shared config in compose.yml and put prod-only settings (resource limits, no bind-mounted source, real restart policies) in compose.prod.yml. Compose merges them in order.
Production must-haves
- Restart policy —
restart: unless-stoppedso services survive reboots. - Resource limits — cap memory and CPU so one service can't starve the host.
- Health-gated startup —
depends_onwithcondition: service_healthy. - Pinned images — real tags or digests, never
latest. - No source bind mounts — ship the built image instead.
Roll it out
Deploy with both files and Compose does the merge. docker compose pull then up -d gives you a rolling-ish update on a single host.
Example
# compose.prod.yml — merged on top of compose.yml
services:
api:
image: ghcr.io/acme/api:1.4.2
restart: unless-stopped
env_file: [.env.production]
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/healthz"]
interval: 30s
timeout: 3s
start_period: 20s
retries: 3
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 3s
retries: 5
volumes:
pgdata:When to use it
- A team maintains a base compose.yml for shared config and a compose.override.prod.yml that adds resource limits, restart policies, and production env vars.
- A CD pipeline runs docker compose -f compose.yml -f compose.prod.yml up -d to merge the base and production configs at deploy time.
- An ops engineer sets memory limits on all compose services to prevent a single runaway service from starving the host.
More examples
Base and production override files
Separates base config from production-only concerns (restarts, limits, logging) into two files merged at deploy time.
# compose.yml (base)
services:
api:
build: .
environment:
NODE_ENV: production
# compose.prod.yml (override)
services:
api:
restart: unless-stopped
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
logging:
driver: json-file
options:
max-size: '10m'
max-file: '3'Deploy with merged compose files
Merges base and production compose files, rebuilds images, starts services, and removes orphaned containers.
docker compose \
-f compose.yml \
-f compose.prod.yml \
up -d --build --remove-orphansRolling update for a service
Pulls the latest api image and recreates only that service without restarting its dependencies.
# Pull the new image version
docker compose pull api
# Recreate only the api service with zero downtime (requires multiple replicas)
docker compose up -d --no-deps api
Discussion