Skip to main content

Docker Compose Cheatsheet — Multi-Container Orchestration

Docker Compose lets you define and run multi-container Docker applications with a single YAML file. From local development to staging environments, Compose streamlines service orchestration, networking, volume management, and environment configuration. This cheatsheet covers the essential CLI commands, the compose file schema, and battle-tested patterns for dev, prod, and CI.

Updated: 2026-07-15·20 commands

Quick Reference

ScenarioCommand
Start all services in foregrounddocker compose up
Start all services in background (detached)docker compose up -d
Rebuild images and startdocker compose up --build -d
Stop and remove containers, networks, volumesdocker compose down
Stop and remove everything including named volumesdocker compose down -v
View live logs from all servicesdocker compose logs -f
View logs from a specific servicedocker compose logs -f web
List running containersdocker compose ps
Restart a specific servicedocker compose restart web
Restart all servicesdocker compose restart
Execute command in a running containerdocker compose exec web bash
Run a one-off command in a new containerdocker compose run --rm web pytest
Pull latest images for all servicesdocker compose pull
Build or rebuild servicesdocker compose build
Check configuration validitydocker compose config
Scale a service to N replicasdocker compose up -d --scale worker=3

Docker Compose CLI Commands

### Starting & Stopping

``bash # Start all services (foreground — Ctrl+C to stop) docker compose up

# Start in detached (background) mode docker compose up -d

# Start specific services only docker compose up -d web db

# Rebuild images before starting (respects Dockerfile changes) docker compose up --build -d

# Stop all running services (keeps containers, can be restarted) docker compose stop

# Stop specific service docker compose stop worker

# Start stopped services docker compose start `

### Tearing Down

`bash # Stop and remove containers + default networks docker compose down

# Also remove named volumes (⚠️ data loss) docker compose down -v

# Remove everything: containers, networks, volumes, images docker compose down --rmi all -v

# Remove orphans (services not in current compose file) docker compose down --remove-orphans `

### Logs & Monitoring

`bash # Stream logs from all services (tail -f style) docker compose logs -f

# Stream logs from a single service docker compose logs -f api

# Show last N lines per service docker compose logs --tail=50

# List running containers managed by compose docker compose ps

# Show resource usage (CPU / memory) docker compose top `

### Restart & Exec

`bash # Restart all services docker compose restart

# Restart a specific service docker compose restart nginx

# Restart with a delay between stops and starts docker compose restart -t 10 web

# Open a shell inside a running container docker compose exec web sh

# Run as a different user docker compose exec -u node web npm test

# Run a one-off command (new container, removed after exit) docker compose run --rm web python manage.py migrate `

### Images & Build

`bash # Pull latest images from registry docker compose pull

# Build (or rebuild) all services docker compose build

# Build without using cache docker compose build --no-cache

# Build a specific service docker compose build web `

---

docker-compose.yml Structure Overview

A docker-compose.yml (or compose.yml) file has three major top-level sections.

`yaml version: "3.9" # optional in modern compose; schema version

services: # 👈 define your containers web: build: . ports: - "8080:80" environment: - NODE_ENV=production volumes: - ./app:/app depends_on: - db

db: image: postgres:16-alpine volumes: - pgdata:/var/lib/postgresql/data environment: POSTGRES_DB: myapp POSTGRES_PASSWORD: changeme

volumes: # 👈 named volumes (persistent storage) pgdata:

networks: # 👈 custom networks (optional) frontend: backend: internal: true `

### Key Service Keys

KeyPurposeExample
imagePre-built image from registryimage: nginx:alpine
buildBuild context (Dockerfile path)build: ./app
portsHost-to-container port mapping"3000:3000"
environmentEnv vars (array or object)NODE_ENV=production
env_fileLoad env from fileenv_file: .env
volumesMount host paths or named volumes./src:/app/src
depends_onStartup order (services)- db
commandOverride default CMDnpm run start
restartRestart policyalways, unless-stopped, on-failure
healthcheckContainer health probetest: ["CMD", "pg_isready"]
networksAttach to custom networks- backend
profilesConditional service activationprofiles: ["dev", "ci"]
deploySwarm/Kubernetes deployment configreplicas: 3
### Volumes: Named vs Bind Mount

`yaml services: app: volumes: # Named volume (managed by Docker, persistent across restarts) - app-data:/data

# Bind mount (host directory directly mapped) - ./src:/app/src

# Anonymous volume (temporary, removed with --rm) - /tmp/cache

volumes: app-data: # declare named volume here `

### Networks: Custom Isolation

`yaml services: frontend: networks: - frontend - backend # dual-homed: accessible from both

api: networks: - backend

db: networks: - backend # db only reachable from api, not frontend

networks: frontend: backend: internal: true # no external (internet) access `

---

Common Compose Patterns

### Dev / Prod Profile Pattern

Use YAML anchoring, extending, or --profile to differentiate environments. The cleanest approach is separate override files.

Base file: compose.yml

`yaml services: app: build: . ports: - "3000:3000" environment: - NODE_ENV=${NODE_ENV:-development}

db: image: postgres:16-alpine environment: POSTGRES_DB: myapp `

Development override: compose.dev.yml

`yaml services: app: volumes: - ./src:/app/src # live reload environment: - DEBUG=true profiles: [dev]

mailhog: image: mailhog/mailhog ports: - "8025:8025" profiles: [dev] `

Production override: compose.prod.yml

`yaml services: app: restart: always environment: - NODE_ENV=production profiles: [prod]

nginx: image: nginx:alpine ports: - "80:80" - "443:443" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro profiles: [prod] `

Usage:

`bash # Dev docker compose -f compose.yml -f compose.dev.yml up -d

# Production docker compose -f compose.yml -f compose.prod.yml up -d `

### Multi-Service Application (Full Stack)

`yaml services: # --- Frontend --- frontend: build: ./frontend ports: - "3000:3000" environment: - REACT_APP_API_URL=http://localhost:8000 depends_on: - api volumes: - ./frontend:/app - /app/node_modules # anonymous volume to avoid overwriting

# --- Backend API --- api: build: ./api ports: - "8000:8000" environment: - DATABASE_URL=postgres://user:pass@db:5432/myapp - REDIS_URL=redis://redis:6379 depends_on: db: condition: service_healthy redis: condition: service_started

# --- Database --- db: image: postgres:16-alpine volumes: - pgdata:/var/lib/postgresql/data environment: POSTGRES_USER: user POSTGRES_PASSWORD: pass POSTGRES_DB: myapp healthcheck: test: ["CMD-SHELL", "pg_isready -U user -d myapp"] interval: 10s timeout: 5s retries: 5 ports: - "5432:5432" # exposed only for local debugging

# --- Cache --- redis: image: redis:7-alpine volumes: - redis-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s

# --- Background Worker --- worker: build: ./api command: celery -A tasks worker --loglevel=info environment: - DATABASE_URL=postgres://user:pass@db:5432/myapp - REDIS_URL=redis://redis:6379 depends_on: - db - redis

# --- Reverse Proxy --- nginx: image: nginx:alpine ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - frontend - api

volumes: pgdata: redis-data: `

### Environment Variable Management

`yaml services: app: # Method 1: inline environment: - NODE_ENV=production - LOG_LEVEL=info

# Method 2: from .env file (supports variable substitution) env_file: - .env - .env.production

# Method 3: using ${} substitution in compose.yml image: myapp:${TAG:-latest} ports: - "${HOST_PORT:-8080}:80" `

.env file (placed next to compose file):

`env TAG=2.1.0 HOST_PORT=8080 POSTGRES_PASSWORD=securepassword `

### Health Checks & Dependencies

`yaml services: app: build: . depends_on: db: condition: service_healthy # wait until healthcheck passes

db: image: postgres:16-alpine healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 3s retries: 5 start_period: 30s # give Postgres time to boot `

### Profiles for Conditional Services

`yaml services: # Always runs app: build: . ports: - "3000:3000"

# Only starts with --profile debug debug-tools: image: nicolaka/netshoot profiles: [debug] depends_on: - app

# Only starts with --profile ci selenium: image: selenium/standalone-chrome profiles: [ci] `

Usage: docker compose --profile debug up or docker compose --profile ci up

### Useful One-Liners

`bash # Restart a single service without bringing others down docker compose restart web

# View logs and follow specific service docker compose logs -f web

# Rebuild a single service and restart it docker compose build web && docker compose up -d web

# Drop into a database container docker compose exec db psql -U postgres myapp

# Copy file into a running container docker compose cp ./init.sql db:/docker-entrypoint-initdb.d/

# Run tests in an isolated environment docker compose run --rm web pytest --cov

# Wipe everything clean (containers, volumes, images) docker compose down -v --rmi all

# Validate compose file without running anything docker compose config

# Export merged compose file (resolves all overrides) docker compose config > merged.yml ``

Compose(20)

CommandLevel
docker compose up
Start all services
Basic
docker compose down
Stop and remove all services
Basic
docker compose logs
View service logs
Basic
docker compose ps
List all service containers
Basic
docker compose build
Build or rebuild service images
Intermediate
docker compose exec
Execute a command in a running container
Intermediate
docker compose restart
Restart all services
Basic
docker compose pull
Pull service images
Basic
docker compose push
Push service images to registry
Intermediate
docker compose run
Run a one-off command
Intermediate
docker compose stop
Stop all services without removing containers
Basic
docker compose rm
Remove stopped service containers
Intermediate
docker compose top
Display running processes
Intermediate
docker compose config
Validate and view Compose configuration
Intermediate
docker compose images
List images used by services
Basic
docker compose create
Create service containers without starting
Intermediate
docker compose events
Monitor real-time events from containers
Expert
docker compose kill
Force stop service containers
Intermediate
docker compose port
Print the public port for a service container
Intermediate
docker compose version
Show Docker Compose version information
Basic

FAQ

This cheatsheet is compiled from official tool documentation. Last updated: 2026-07-15.