# Docker Compose Patterns ## Pattern: Multi-Service Application Complete pattern for a typical web application with API, database, cache, and reverse proxy. ```yaml version: '3.8' services: # Reverse Proxy nginx: image: nginx:alpine ports: - "80:80" - "443:443" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro - ./ssl:/etc/nginx/ssl:ro depends_on: - api networks: - frontend deploy: resources: limits: cpus: '0.5' memory: 256M healthcheck: test: ["CMD", "nginx", "-t"] interval: 30s timeout: 10s retries: 3 # API Service api: build: context: ./api dockerfile: Dockerfile environment: - NODE_ENV=production - DATABASE_URL=postgres://db:5432/app - REDIS_URL=redis://cache:6379 depends_on: db: condition: service_healthy cache: condition: service_started networks: - frontend - backend deploy: replicas: 3 resources: limits: cpus: '1' memory: 1G reservations: cpus: '0.5' memory: 512M healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"] interval: 30s timeout: 10s retries: 3 start_period: 60s # Database db: image: postgres:15-alpine environment: POSTGRES_DB: app POSTGRES_USER: ${DB_USER:-app} POSTGRES_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD required} volumes: - postgres-data:/var/lib/postgresql/data - ./init-scripts:/docker-entrypoint-initdb.d:ro networks: - backend healthcheck: test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"] interval: 10s timeout: 5s retries: 5 deploy: resources: limits: cpus: '2' memory: 2G # Cache cache: image: redis:7-alpine command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru volumes: - redis-data:/data networks: - backend healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 networks: frontend: driver: bridge backend: driver: bridge internal: true # No external access volumes: postgres-data: driver: local redis-data: driver: local ``` ## Pattern: Development Override Development-specific configuration with hot reload and debugging. ```yaml # docker-compose.dev.yml version: '3.8' services: api: build: context: ./api dockerfile: Dockerfile.dev volumes: - ./api/src:/app/src:ro - ./api/tests:/app/tests:ro - /app/node_modules environment: - NODE_ENV=development - DEBUG=app:* ports: - "3000:3000" - "9229:9229" # Node.js debugger command: npm run dev db: ports: - "5432:5432" # Expose for local tools cache: ports: - "6379:6379" # Expose for local tools ``` ```bash # Usage docker-compose -f docker-compose.yml -f docker-compose.dev.yml up ``` ## Pattern: Production Override Production-optimized configuration with security and performance settings. ```yaml # docker-compose.prod.yml version: '3.8' services: api: image: myapp/api:${VERSION} deploy: replicas: 3 update_config: parallelism: 1 delay: 10s failure_action: rollback rollback_config: parallelism: 1 delay: 10s resources: limits: cpus: '1' memory: 1G reservations: cpus: '0.5' memory: 512M environment: - NODE_ENV=production secrets: - db_password - jwt_secret logging: driver: "json-file" options: max-size: "10m" max-file: "5" secrets: db_password: external: true jwt_secret: external: true ``` ```bash # Usage docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d ``` ## Pattern: Health Check Dependency Waiting for dependent services to be healthy before starting. ```yaml services: app: depends_on: db: condition: service_healthy cache: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 start_period: 60s db: healthcheck: test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER"] interval: 10s timeout: 5s retries: 5 cache: healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 ``` ## Pattern: Secrets Management Using Docker secrets for sensitive data (Swarm mode). ```yaml services: app: secrets: - db_password - api_key - jwt_secret environment: - DB_PASSWORD_FILE=/run/secrets/db_password - API_KEY_FILE=/run/secrets/api_key - JWT_SECRET_FILE=/run/secrets/jwt_secret secrets: db_password: file: ./secrets/db_password.txt api_key: file: ./secrets/api_key.txt jwt_secret: external: true # Created via: echo "secret" | docker secret create jwt_secret - ``` ## Pattern: Resource Limits Setting resource constraints for containers. ```yaml services: api: deploy: resources: limits: cpus: '1.0' memory: 1G reservations: cpus: '0.5' memory: 512M # Alternative for non-Swarm mem_limit: 1G memswap_limit: 1G cpus: 1 ``` ## Pattern: Network Isolation Segmenting networks for security. ```yaml services: web: networks: - frontend - backend api: networks: - backend - database db: networks: - database networks: frontend: driver: bridge backend: driver: bridge database: driver: bridge internal: true # No internet access ``` ## Pattern: Volume Management Different volume types for different use cases. ```yaml services: app: volumes: # Named volume (managed by Docker) - app-data:/app/data # Bind mount (host directory) - ./config:/app/config:ro # Anonymous volume (for node_modules) - /app/node_modules # tmpfs (temporary in-memory) - type: tmpfs target: /tmp tmpfs: size: 100M volumes: app-data: driver: local labels: - "app=myapp" - "type=persistent" ``` ## Pattern: Logging Configuration Configuring logging drivers and options. ```yaml services: app: logging: driver: "json-file" # Default options: max-size: "10m" max-file: "3" labels: "app,environment" tag: "{{.ImageName}}/{{.Name}}" # Syslog logging app-syslog: logging: driver: "syslog" options: syslog-address: "tcp://logserver:514" syslog-facility: "daemon" tag: "myapp" # Fluentd logging app-fluentd: logging: driver: "fluentd" options: fluentd-address: "localhost:24224" tag: "myapp.api" ``` ## Pattern: Multi-Environment Managing multiple environments with overrides. ```bash # Directory structure # docker-compose.yml # Base configuration # docker-compose.dev.yml # Development overrides # docker-compose.staging.yml # Staging overrides # docker-compose.prod.yml # Production overrides # .env # Environment variables # .env.dev # Development variables # .env.staging # Staging variables # .env.prod # Production variables # Development docker-compose --env-file .env.dev \ -f docker-compose.yml -f docker-compose.dev.yml up # Staging docker-compose --env-file .env.staging \ -f docker-compose.yml -f docker-compose.staging.yml up -d # Production docker-compose --env-file .env.prod \ -f docker-compose.yml -f docker-compose.prod.yml up -d ``` ## Pattern: CI/CD Testing Running tests in isolated containers. ```yaml # docker-compose.test.yml version: '3.8' services: app: build: context: . dockerfile: Dockerfile environment: - NODE_ENV=test - DATABASE_URL=postgres://test:test@db:5432/test depends_on: - db command: npm test networks: - test-network db: image: postgres:15-alpine environment: POSTGRES_DB: test POSTGRES_USER: test POSTGRES_PASSWORD: test networks: - test-network networks: test-network: driver: bridge ``` ```bash # CI pipeline docker-compose -f docker-compose.test.yml up --abort-on-container-exit --exit-code-from app docker-compose -f docker-compose.test.yml down -v ```