The Conventional Wisdom

"Use Kubernetes in production, Docker Compose is just for development." You've probably heard this. It's not wrong — but it's also not the whole story. For small teams, single-server setups, and projects that don't need horizontal scaling, Docker Compose in production is a completely valid choice.

This very website runs on Docker Compose in production — on a single AWS t3.micro instance. Here's what I've learned.

When Docker Compose in Production Makes Sense

  • Single server setup — your app fits on one machine (most small businesses do)
  • Low traffic — under ~1,000 concurrent users
  • Small team — 1-5 developers who don't want Kubernetes complexity
  • Predictable load — no need for auto-scaling
  • Budget constraints — one EC2 instance costs $15-30/month vs $150+ for managed Kubernetes

The Real Limitations

Docker Compose has genuine limitations in production:

  • No auto-healing — if a container crashes, you need a process monitor (or a restart policy) to bring it back
  • No horizontal scaling — you can't easily add more web servers
  • No rolling deployments — deploys cause a brief downtime window
  • Single point of failure — if the server goes down, everything goes down

Making It Production-Ready

With a few additions, Docker Compose becomes quite robust:

services:
web:
  restart: unless-stopped    # auto-restart on crash
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
    interval: 30s
    retries: 3
nginx:
  restart: unless-stopped
db:
  restart: unless-stopped
  volumes:
    - postgres_data:/var/lib/postgresql/data  # persistent data

Add restart: unless-stopped to every service. It ensures containers come back up after a server reboot or crash. Combine with a healthcheck for the web service.

Deployment Without Downtime

Zero-downtime deploys with Docker Compose require a bit of creativity. One approach:

  1. Sync new code to the server (rsync)
  2. Build the new image: docker compose build web
  3. Run migrations: docker compose exec web rails db:migrate
  4. Reload: docker compose up -d --no-deps web

Nginx continues serving the old container while the new one starts. The gap is typically under 5 seconds.

When to Move to Kubernetes

Graduate to Kubernetes when you need: multiple servers, auto-scaling, canary deployments, or if your team grows beyond 10 engineers. For everything else, Docker Compose is fast, simple, and reliable enough.

Need help containerizing your application or setting up a production Docker environment? Browse our containerization services.