🐳

Docker Compose Guide

Verified

by Community

Guides you through creating Docker Compose configurations for local development and production, including networking, volumes, health checks, and common service patterns.

dockercontainersdevopsdevelopmentcompose

Docker Compose Guide

Set up multi-container applications efficiently with Docker Compose.

Usage

  1. Define your services in docker-compose.yml with appropriate images and build contexts
  2. Configure networking: default bridge network or custom networks for service isolation
  3. Set up volumes for data persistence and development hot-reloading
  4. Add health checks to ensure services start in the correct order
  5. 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.yml with 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.2 not postgres:latest — latest changes without warning and breaks builds
  • Use .env file for configuration, never hardcode secrets in docker-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: 512M prevents one container from consuming all host memory
  • Use docker compose logs -f service_name for debugging, not docker logs — Compose manages the container names
  • Run docker compose down -v to completely reset (removes volumes too) — useful when you need a fresh start, but destructive