K8sCalc

docker

Docker Compose Generator

Generate a production-ready docker-compose.yml with your app, optional PostgreSQL or MySQL database, Redis, and nginx reverse proxy. Includes health checks and named volumes.

Docker Compose Production Patterns

Docker Compose is the simplest way to run multi-container applications. Here are patterns for production use.

Health Checks

yaml
postgres:
  healthcheck:
    test: ["CMD-SHELL", "pg_isready -U postgres"]
    interval: 10s
    timeout: 5s
    retries: 5

Use depends_on: condition: service_healthy so your app waits for the database to be ready before starting.

Environment Variables via .env

bash
# .env (git-ignored)
POSTGRES_PASSWORD=super_secret
APP_SECRET_KEY=another_secret
yaml
# docker-compose.yml
environment:
  - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}

Resource Limits

yaml
services:
  myapp:
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

Updating Without Downtime

bash
docker compose pull myapp
docker compose up -d --no-deps myapp

Frequently Asked Questions

When should I use Docker Compose vs Kubernetes?

Docker Compose is ideal for single-server deployments, development environments, and small production workloads. Kubernetes adds value when you need multi-node scheduling, horizontal pod autoscaling, rolling updates without downtime, or self-healing at scale. If you're running on a single Hetzner VPS, Compose is often the right choice.

What does 'unless-stopped' restart policy do?

The container restarts automatically if it exits (crash, OOM) but stays stopped if you explicitly ran 'docker compose stop'. This is safer than 'always' which would restart even after intentional stops. Use 'always' only if you want the service to survive even docker daemon restarts.

How do I pass secrets to Docker Compose?

Never hardcode secrets in docker-compose.yml. Use a .env file (add to .gitignore): create a .env file with DATABASE_PASSWORD=secret, then reference it in compose with ${DATABASE_PASSWORD}. For production, use Docker Secrets or inject via CI/CD environment variables.

Why use named volumes instead of bind mounts for databases?

Named volumes (postgres-data:) are managed by Docker and survive container removal. Bind mounts (./data:/var/lib/postgresql/data) depend on host directory permissions and can cause permission errors. For databases, named volumes are more reliable and portable.