Docker Compose Guide
Set up multi-container applications efficiently with Docker Compose.
Usage
- Define your services in
docker-compose.ymlwith appropriate images and build contexts - Configure networking: default bridge network or custom networks for service isolation
- Set up volumes for data persistence and development hot-reloading
- Add health checks to ensure services start in the correct order
- Use profiles and override files for dev vs production configurations
Examples
- Web app + database + cache: Three services:
app(Node.js, builds from Dockerfile),db(postgres:16, volume-mounted data),cache(redis:7). App depends_on db and cache with health checks. Ports: app exposes 3000, db internal only (5432 not published), cache internal only. Named volume for postgres data persists across container recreations - Development overrides: Base
docker-compose.ymlwith production-like config.docker-compose.override.yml(auto-loaded in dev): adds volume mounts for hot reload, exposes debug ports, uses development environment variables, removes resource limits. Production uses:docker compose -f docker-compose.yml -f docker-compose.prod.yml up - Health checks:
healthcheck: test: ["CMD", "pg_isready", "-U", "postgres"], interval: 10s, timeout: 5s, retries: 5. Then in dependent service:depends_on: db: condition: service_healthy. This ensures your app doesn't start until the database is actually ready to accept connections — not just that the container is running
Guidelines
- Always pin image versions:
postgres:16.2notpostgres:latest— latest changes without warning and breaks builds - Use
.envfile for configuration, never hardcode secrets indocker-compose.yml(it's committed to git) - Named volumes persist data; bind mounts are for development source code. Don't use bind mounts for database data in production
- Set memory limits in production:
deploy.resources.limits.memory: 512Mprevents one container from consuming all host memory - Use
docker compose logs -f service_namefor debugging, notdocker logs— Compose manages the container names - Run
docker compose down -vto completely reset (removes volumes too) — useful when you need a fresh start, but destructive