Skip to content
Back to Cloud Services

Docker Compose for production: when it's enough

Run a multi-container app in production with Compose, including restart policies, healthchecks, and resource limits.

Docker HostingIntermediate

Why

For a single-host app (small API + DB + cache), Compose is simpler than Kubernetes, needs no cluster, and supports restart policies, healthchecks, and resource limits. It's enough up to ~5 services on one beefy VPS.

Docker is used by 59% of professional developers per the Stack Overflow 2024 survey. Docker Hub has 15M+ public images, and OCI image spec adoption means containers run identically across Docker, Podman, and containerd.

When

Use for small single-host deployments, staging environments, or as a stepping stone before K8s. Avoid for HA, multi-host, or auto-scaling needs.

How

1. Write docker-compose.prod.yml with: restart: unless-stopped, healthcheck, deploy.resources.limits (cpus, memory), and a read-only rootfs where possible. 2. Run with `docker compose -f docker-compose.prod.yml up -d`. 3. Use `docker compose --profile` to separate one-off tasks (migrations, cron). 4. Back up volumes with `docker run --rm -v app_db:/db -v /backups:/bk alpine tar czf /bk/db.tgz /db`. 5. Monitor with a sidecar cAdvisor or just `docker stats`.

Example

# docker-compose.prod.yml services: api: image: ghcr.io/me/api:1.0 restart: unless-stopped read_only: true tmpfs: ["/tmp"] healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 3s retries: 3 deploy: resources: limits: { cpus: "1.0", memory: 512M } depends_on: db: { condition: service_healthy } db: image: postgres:16-alpine restart: unless-stopped volumes: ["dbdata:/var/lib/postgresql/data"] healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s volumes: { dbdata: {} }

Common Problems

  • ⚠No healthcheck means depends_on starts the API before the DB is ready — add condition: service_healthy.
  • ⚠No resource limits let one container OOM the whole host — set deploy.resources.limits on every service.
  • ⚠Restart: always restarts even on docker compose down — use unless-stopped instead.

Best Practices

  • ✓Use docker compose -f docker-compose.prod.yml (separate from dev) to avoid dev-only env vars in prod.
  • ✓Set read_only: true + tmpfs for /tmp to limit filesystem attack surface.
  • ✓Schedule nightly volume backups via a cron-sidecar service in the same compose file.

FAQ

What is Docker Compose for production: when it's enough and what problem does it solve?

Run a multi-container app in production with Compose, including restart policies, healthchecks, and resource limits. It lets developers deploy, store, and scale without self-managing infrastructure — a core reference for cloud service selection.

How do I get started with Docker Compose for production: when it's enough in 5 minutes?

Two steps to run it: (1) Write docker-compose.prod.yml with: restart: unless-stopped, healthcheck, deploy.resources.limits (cpus, memory), and a read-only rootfs where possible.; (2) Run with `docker compose -f docker-compose.prod.yml up -d`.. Validate on the free tier first, then wire into production.

What is the #1 pitfall with Docker Compose for production: when it's enough?

The most frequent issue is: No healthcheck means depends_on starts the API before the DB is ready — add condition: service_healthy.. Run a pre-launch checklist item by item, and add policy/config scanning in CI.

What are the best practices for Docker Compose for production: when it's enough?

Best practices for Docker Compose for production: when it's enough include: Use docker compose -f docker-compose.prod.yml (separate from dev) to avoid dev-only env vars in prod.; Set read_only: true + tmpfs for /tmp to limit filesystem attack surface.; Schedule nightly volume backups via a cron-sidecar service in the same compose file.. The first one — "Use docker compose -f docker-compose.prod.yml (separate from dev) to avoid dev-only env vars in prod." — should be a team default baked into your IaC templates.

How do I control cost and avoid bill surprises with Docker Compose for production: when it's enough?

Three ways to prevent overspend: (1) tag every resource with env/team and enable billing alarms; (2) set budget thresholds to trigger Slack/email alerts; (3) review idle resources in Cost Explorer regularly and clean them up. Most Docker Compose for production: when it's enough options offer a free tier — validate within free quota before scaling.