Docker Compose Cheat Sheet
Essential Docker Compose CLI commands and YAML syntax for defining and running multi-container applications locally.
CLI Basics
Core commands to manage a Compose project.
docker compose up # Create and start all servicesdocker compose up -d # Start in detached modedocker compose down # Stop and remove containers/networksdocker compose down -v # Also remove named volumesdocker compose ps # List project containersdocker compose logs -f web # Tail logs for the 'web' servicedocker compose exec web sh # Shell into a running servicedocker compose build # Build/rebuild imagesdocker compose restart web # Restart one service
compose.yaml Structure
A typical multi-service application definition.
services: web: build: . ports: - "3000:3000" environment: - NODE_ENV=production depends_on: - db volumes: - ./src:/app/src db: image: postgres:15 environment: POSTGRES_PASSWORD: secret volumes: - db-data:/var/lib/postgresql/datavolumes: db-data:
Key Directives
Common top-level and service-level keys.
- depends_on- Controls startup order; use condition: service_healthy to wait for a healthcheck
- healthcheck- Defines test/interval/retries to determine when a service is 'healthy'
- networks- Custom networks for controlling which services can reach each other
- env_file- Loads environment variables from a .env-style file into the service
- profiles- Tags services so they only start when a matching --profile flag is passed
- extends / include- Reuse configuration across compose files or include another compose file
Multi-file / Override
Layer environment-specific overrides on a base file.
# docker-compose.override.yml is merged automatically with docker-compose.ymldocker compose -f docker-compose.yml -f docker-compose.prod.yml up -d# Validate merged config without starting anythingdocker compose config
Resource Limits & Restart Policy
Constrain CPU/memory and define restart behavior without a Swarm using the Compose deploy key.
services: worker: image: myorg/worker:2.3 deploy: resources: limits: cpus: "1.50" memory: 512M reservations: cpus: "0.25" memory: 128M restart: unless-stopped ulimits: nofile: soft: 65536 hard: 65536 stop_grace_period: 30s stop_signal: SIGTERM
Multi-Stage Build Targets & Cache
Target a specific Dockerfile stage and control layer caching directly from compose.yaml.
services: app: build: context: . dockerfile: Dockerfile target: dev args: BUILDKIT_INLINE_CACHE: "1" cache_from: - myorg/app:cache x-bake: platforms: ["linux/amd64", "linux/arm64"] develop: watch: - action: sync path: ./src target: /app/src - action: rebuild path: package.json
Healthcheck-Gated Startup Chains
Chain three services so each only starts once its dependency is verifiably healthy, not just running.
services: db: image: postgres:15 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 3s retries: 10 start_period: 10s migrate: build: ./migrate depends_on: db: condition: service_healthy restart: "no" api: build: . depends_on: migrate: condition: service_completed_successfully db: condition: service_healthy
Secrets & Configs (File-Based)
Mount sensitive data and config files without baking them into images or plaintext env vars.
services: api: image: myorg/api:1.0 secrets: - db_password configs: - source: app_config target: /etc/app/config.yamlsecrets: db_password: file: ./secrets/db_password.txtconfigs: app_config: file: ./config/app.yaml# Inside the container: secret at /run/secrets/db_password (root-only, 0400)
Advanced Directives & Behaviors
Less common but powerful compose.yaml features for real deployments.
- x- (extension fields)- Top-level keys prefixed x- are ignored by Compose and used with YAML anchors (&/*) to DRY up repeated config blocks
- networks.driver_opts- Pass driver-specific options (e.g. MTU) to custom bridge networks defined at the top level
- COMPOSE_PROJECT_NAME- Env var (or -p flag) controlling the resource name prefix, letting the same file run as isolated stacks side by side
- docker compose run --rm- Runs a one-off command in a new container using a service's image/config, removing it afterward; ignores ports by default
- read_only + tmpfs- Mount the container root filesystem read-only and provide writable tmpfs mounts for the few paths that need writes
- docker compose config --profiles- Lists profiles defined in the file so CI can validate which optional service groups exist before deployment
Use depends_on with condition: service_healthy plus a real healthcheck instead of sleep hacks, so dependent services only start once the database is actually ready to accept connections.