Skip to main content

Production-Grade Docker Compose Patterns

Engineering standards for secure deployment of multi-container services on VPS without the complexity of Kubernetes: resource limits, isolated networks, health checks, and secret management.

1. Concept Overview & Systemic Problem

Many developers use Docker Compose only locally, viewing it as a "development tool," while attempting to deploy heavy clusters in production or, conversely, running everything on the host manually via pm2 or nohup:

  • Without memory limits, a single hung process leaks and triggers the Linux OOM-killer, which kills the database.
  • Logs from a single container can grow to 50 GB over three months, filling up the root partition / and paralyzing the server.
  • Containers are on a shared bridge network, so a compromised web service has direct access to the internal database ports.

Production-Grade Docker Compose is a collection of proven engineering patterns that transforms a single docker-compose.prod.yml file into a reliable, secure, and disaster-resistant platform.

2. Architectural Taxonomy & Mental Model

┌─────────────────────────────────────────────────────────────┐
│              PRODUCTION DOCKER COMPOSE TOPOLOGY             │
├─────────────────────────────────────────────────────────────┤
│ 1. SEPARATED INTERNAL NETWORKS                              │
│    • `public-network`: Only Traefik/Caddy ➔ Web App (Port 80/443)│
│    • `backend-network`: Only Web App ➔ Postgres DB & Redis  │
│    ➔ Database is physically isolated from the external world!│
├─────────────────────────────────────────────────────────────┤
│ 2. RESILIENCE & LIFECYCLE CONTROLS                          │
│    • `restart: unless-stopped` (Auto-start after VPS reboot)│
│    • Healthchecks: `test: ["CMD", "curl", "-f", "/health"]` │
│    • Depends_on with condition: `service_healthy`           │
├─────────────────────────────────────────────────────────────┤
│ 3. RESOURCE HARD CAPS (Preventing Host Crash)               │
│    • Memory limit: `max: 2G` | CPU: `1.5` cores             │
│    • Log Rotation: `max-size: 10m` | `max-file: 3`          │
└─────────────────────────────────────────────────────────────┘

3. Technical Pipeline & Internal Mechanics

01. Reference Production Fragment for PostgreSQL Database

services:
  db:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB_FILE: /run/secrets/db_name
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_name
      - db_password
    volumes:
      - pgdata:/var/lib/postgresql/data
    networks:
      - internal-tier
    deploy:
      resources:
        limits:
          memory: 1536M
          cpus: "1.0"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

4. Production Engineering Scenarios

01. Database Security and Access Control

Ensure that database ports are not exposed to the public. Use expose: ["5432"] or bind the port strictly to localhost: 127.0.0.1:5432:5432.

02. Resource Management and Limits

Implement resource limits to prevent host crashes. Specify memory and CPU limits in the deploy.resources.limits section to ensure stability under load.

03. Log Management and Retention

Configure log rotation to prevent disk overflow. Set max-size and max-file options in the logging configuration to manage log growth effectively.

5. Pitfalls, Common Mistakes & Security

  • Exposing Database Ports to the World: Using the ports: ["5432:5432"] directive automatically opens the port on all public interfaces, bypassing even UFW firewall rules (due to Docker's iptables behavior). Use expose: ["5432"] or bind the port strictly to localhost: 127.0.0.1:5432:5432.
  • Data Loss from Anonymous Volumes: Forgetting to specify a named volume (volumes: pgdata:/data) can lead to irreversible database destruction during the docker compose down -v command.
/ Frequently Asked QuestionsSchema.org FAQPage

FAQ: Production-Grade Docker Compose Patterns

For 95% of products (up to several dozen servers), Kubernetes is an over-engineering complexity that wastes engineers' time on maintaining manifests. A well-designed Docker Compose on a quality VPS at Hetzner can handle millions of requests per day with minimal resource costs.
/ Internal links
All terms