Docker Compose is not just for development. With the right patterns, it runs production workloads on single servers reliably.
Health Checks
services:
api:
image: my-api:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
postgres:
image: postgres:16-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3Dependency Management
services:
api:
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
restart: unless-stoppedResource Limits
services:
api:
deploy:
resources:
limits:
cpus: '2.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 256M
replicas: 2Logging
services:
api:
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
tag: "{{.Name}}"
# Or centralized logging
loki-api:
logging:
driver: loki
options:
loki-url: "http://loki:3100/loki/api/v1/push"
loki-retries: "3"Without max-size, Docker logs grow unbounded and fill the disk.
Master this topic with hands-on labs
Go beyond reading — build real projects in sandboxed environments with expert video guidance.
Browse Courses →Networking
services:
frontend:
networks:
- frontend-net
api:
networks:
- frontend-net
- backend-net
postgres:
networks:
- backend-net # Not accessible from frontend
networks:
frontend-net:
backend-net:
internal: true # No external accessSecrets
services:
api:
secrets:
- db_password
- jwt_secret
environment:
DB_PASSWORD_FILE: /run/secrets/db_password
secrets:
db_password:
file: ./secrets/db_password.txt
jwt_secret:
file: ./secrets/jwt_secret.txtRead in application:
import { readFileSync } from 'fs';
const dbPassword = process.env.DB_PASSWORD_FILE
? readFileSync(process.env.DB_PASSWORD_FILE, 'utf8').trim()
: process.env.DB_PASSWORD;Multi-Environment Configuration
Base + Override Pattern
# docker-compose.yml (base)
services:
api:
image: my-api:latest
environment:
NODE_ENV: production
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
postgres:
image: postgres:16-alpine
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:# docker-compose.override.yml (development — auto-loaded)
services:
api:
build: .
environment:
NODE_ENV: development
DEBUG: "*"
volumes:
- ./src:/app/src
ports:
- "3000:3000"
postgres:
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: devpassword# docker-compose.prod.yml (production overrides)
services:
api:
image: registry.internal/my-api:v2.1.0
deploy:
replicas: 3
resources:
limits:
memory: 1G
restart: unless-stopped
postgres:
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
volumes:
- /data/postgres:/var/lib/postgresql/data
secrets:
db_password:
file: /etc/secrets/db_password# Development (auto-loads override)
docker compose up
# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -dReverse Proxy with Caddy
services:
caddy:
image: caddy:2-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy-data:/data
restart: unless-stopped
depends_on:
api:
condition: service_healthy
api:
image: my-api:latest
expose:
- "3000" # Not published to host, only internal
restart: unless-stopped
volumes:
caddy-data:# Caddyfile
app.example.com {
reverse_proxy api:3000
encode gzip
}Caddy handles HTTPS automatically with Let's Encrypt.
Get weekly IT automation tips
Docker, Ansible, Terraform, MLOps — curated insights delivered to your inbox. No spam.
Subscribe Free →Zero-Downtime Deploys
#!/bin/bash
set -euo pipefail
# Pull new image
docker compose pull api
# Rolling update (one at a time with health checks)
docker compose up -d --no-deps --scale api=3 api
# Wait for new containers to be healthy
sleep 10
# Remove old containers
docker compose up -d --no-deps --scale api=2 apiBackup Pattern
services:
backup:
image: postgres:16-alpine
entrypoint: /bin/sh
command: >
-c "while true; do
pg_dump -h postgres -U postgres mydb | gzip > /backups/db-$$(date +%Y%m%d_%H%M%S).sql.gz;
find /backups -name '*.sql.gz' -mtime +7 -delete;
sleep 86400;
done"
volumes:
- ./backups:/backups
depends_on:
postgres:
condition: service_healthyMonitoring Stack
services:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
ports:
- "9090:9090"
grafana:
image: grafana/grafana:latest
volumes:
- grafana-data:/var/lib/grafana
ports:
- "3001:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
node-exporter:
image: prom/node-exporter:latest
pid: host
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
volumes:
prometheus-data:
grafana-data:What's Next?
Our Docker Fundamentals course covers Docker Compose for development and production environments. Node.js REST APIs teaches containerized API development. First lessons are free.
---
Ready to go deeper? Check out our hands-on course: Docker Fundamentals — practical exercises you can follow along on your own machine.
Ready to learn by doing?
Stop reading tutorials — start building. Expert video courses with hands-on labs in real sandboxed environments.
Related Articles
Quality vs Throughput in DevOps
High throughput and high quality are not mutually exclusive in DevOps. Learn how to increase deployment frequency without sacrificing reliability.
Docker Volumes and Persistent Data
Manage persistent data in Docker with named volumes and bind mounts. Backup strategies, restore procedures, and container data sharing.
Docker Tutorial for Beginners 2026
Complete Docker tutorial for beginners. Learn containers, images, Dockerfiles, volumes, networking, and Docker Compose step by step.
Docker Compose Tutorial for Devs
Master Docker Compose for local development. Multi-service stacks with databases, caching, and hot reload in one command.
Docker Image Optimization Guide
Reduce Docker image size by up to 90%. Multi-stage builds, layer caching, distroless base images, and build-time best practices.
Building Docker Images from MLflow Models
Package your MLflow models as Docker containers for portable, reproducible deployments. Step-by-step guide with best practices.
Explore topics
Browse more articles on the topics covered here.