Docker Compose Cheatsheet

Complete Docker Compose reference guide covering services, volumes, networks, commands, and configurations. Everything you need for container orchestration.
Docker Compose Cheatsheet
Introduction
Docker Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application's services, networks, and volumes. Then, with a single command, you create and start all the services from your configuration.
Official Documentation:
Getting Started
Basic Example
Here's a simple docker-compose.yml file:
# docker-compose.yml
version: '3.8'
services:
web:
build:
context: ./Path
dockerfile: Dockerfile
ports:
- "5000:5000"
volumes:
- .:/code
redis:
image: redisVersion 1 to 2 Migration
Docker Compose is now integrated into the official Docker installation. The syntax change is simple:
- V1:
docker-compose ARG - V2:
docker compose ARG(no hyphen)
The functionality has only improved with this change.
Essential Commands
Version and Configuration
# Check Docker Compose version
docker compose version
# Validate and view the compose file
docker compose configContainer Lifecycle
# Start services
docker compose start
# Stop services
docker compose stop
# Restart services
docker compose restart
# Run a one-time command
docker compose run web bashCreating and Managing Services
# Create containers without starting them
docker compose create
# Attach to a running container
docker compose attach web
# Pause services
docker compose pause
# Unpause services
docker compose unpauseUp and Down
# Wait for services to be running|healthy
docker compose wait
# Create and start containers
docker compose up
# Create and start in detached mode
docker compose up -d
# Build images before starting
docker compose up --build
# Stop and remove containers, networks
docker compose down
# Stop and remove containers, networks, volumes
docker compose down -vMonitoring and Logs
# List containers
docker compose ps
# Display running processes
docker compose top
# Stream container events
docker compose events
# View output from containers
docker compose logs
# Follow log output
docker compose logs -f
# Tail last 100 lines
docker compose logs --tail=100Building and Images
# List images used by services
docker compose images
# Build or rebuild services
docker compose build
# Build without cache
docker compose build --no-cache
# Push service images
docker compose push
# Copy files/folders between service and local filesystem
docker compose cp web:/app/file.txt ./file.txt
# Execute command in running container
docker compose exec web bashConfiguration Reference
Building Services
Build from Dockerfile
web:
build: .
args:
APP_HOME: appCustom Dockerfile
web:
build:
context: ./dir
dockerfile: Dockerfile.dev
args:
buildno: 1
gitcommithash: cdc3b19Build from Image
web:
image: ubuntu
# or specific version
image: ubuntu:22.04
image: tutum/influxdb
image: example-registry:4000/postgresql
image: a4bc65fd # image IDPorts
Port Mapping
services:
web:
ports:
- "3000" # Random host port to container 3000
- "8000:80" # Host 8000 to container 80
- "127.0.0.1:8001:8001" # Localhost only
- "6060:6060/udp" # UDP portExpose Ports
services:
web:
# Expose ports to linked services (not to host)
expose:
- "3000"
- "8000"Commands
Override Default Command
services:
web:
# String format
command: bundle exec thin -p 3000
# Array format (recommended)
command: [bundle, exec, thin, -p, 3000]Override Entrypoint
services:
web:
# String format
entrypoint: /app/start.sh
# Array format
entrypoint: [php, -d, vendor/bin/phpunit]Environment Variables
Direct Definition
services:
web:
environment:
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET:
# Alternative array syntax
environment:
- RACK_ENV=development
- SHOW=trueFrom File
services:
web:
# Single file
env_file: .env
# Multiple files (later files override earlier)
env_file:
- .env
- .env.developmentExample .env file:
RACK_ENV=development
SECRET_KEY=mysecretkey
DATABASE_URL=postgresql://localhost/mydb
Dependencies
Links (Legacy)
services:
web:
# Makes the 'db' service available as hostname 'database'
links:
- db:database
- redisDepends On (Simple)
services:
web:
depends_on:
- db
- redisDepends On (Advanced)
services:
web:
depends_on:
db:
condition: service_healthy
db-init:
condition: service_completed_successfullyConditions:
service_started- Default, wait for service to startservice_healthy- Wait for healthcheck to passservice_completed_successfully- Wait for run-once service to complete
Volumes
Volume Types
services:
db:
volumes:
# Anonymous volume
- /var/lib/mysql
# Host path (bind mount)
- ./cache:/tmp/cache
# Named volume
- datavolume:/var/lib/mysql
# Read-only mount
- ./code:/code:ro
# Define named volumes
volumes:
datavolume:Named Volume Configuration
services:
db:
volumes:
- dbdata:/var/lib/postgresql/data
volumes:
dbdata:
driver: local
driver_opts:
type: none
o: bind
device: /data/dbNetworking
Default Network
By default, Compose creates a single network for your app. Each container joins this network and can communicate with other containers.
Custom Networks
services:
web:
networks:
- frontend
- backend
db:
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridgeExternal Network
networks:
default:
external:
name: my-pre-existing-networkNetwork Aliases
services:
web:
networks:
frontend:
aliases:
- webserver
- wwwRestart Policies
services:
web:
restart: "no" # Never restart (default)
restart: always # Always restart
restart: on-failure # Restart on failure
restart: unless-stopped # Always restart unless explicitly stoppedHealthcheck
services:
web:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40sTest Options:
["CMD", "executable", "arg1"]- Execute command directly["CMD-SHELL", "command"]- Execute with shell["NONE"]- Disable healthcheck
Advanced Features
Labels
Add metadata to containers:
services:
web:
labels:
com.example.description: "Accounting web app"
com.example.department: "Finance"
com.example.version: "1.0"DNS Configuration
services:
web:
# Single DNS server
dns: 8.8.8.8
# Multiple DNS servers
dns:
- 8.8.8.8
- 8.8.4.4
# Custom DNS search domains
dns_search:
- dc1.example.com
- dc2.example.comDevice Mapping
services:
web:
devices:
- "/dev/ttyUSB0:/dev/ttyUSB0"
- "/dev/sda:/dev/xvda:rwm"External Links
Link to containers not managed by this docker-compose.yml:
services:
web:
external_links:
- redis_1
- project_db_1:mysql
- project_db_1:postgresqlExtra Hosts
Add hostname mappings:
services:
web:
extra_hosts:
- "somehost:192.168.1.100"
- "otherhost:192.168.1.101"User and Group
services:
web:
# Run as specific user
user: root
# Run as user:group
user: 1000:1000
# Run as named user
user: www-dataWorking Directory
services:
web:
working_dir: /appResource Limits
services:
web:
deploy:
resources:
limits:
cpus: '0.50'
memory: 512M
reservations:
cpus: '0.25'
memory: 256MLogging
services:
web:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"Logging Drivers:
json-file- Default JSON loggingsyslog- Syslog loggingjournald- Journald logginggelf- Graylog Extended Log Formatfluentd- Fluentd loggingawslogs- AWS CloudWatch Logs
Common Patterns
Multi-Stage Application
version: '3.8'
services:
# Database
db:
image: postgres:15
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: myapp
POSTGRES_USER: dbuser
POSTGRES_PASSWORD: dbpass
healthcheck:
test: ["CMD-SHELL", "pg_isready -U dbuser"]
interval: 10s
timeout: 5s
retries: 5
# Cache
redis:
image: redis:alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
# Backend API
api:
build:
context: ./api
dockerfile: Dockerfile
ports:
- "8000:8000"
environment:
DATABASE_URL: postgresql://dbuser:dbpass@db/myapp
REDIS_URL: redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
volumes:
- ./api:/app
command: python manage.py runserver 0.0.0.0:8000
# Frontend
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
REACT_APP_API_URL: http://localhost:8000
depends_on:
- api
volumes:
- ./frontend:/app
- /app/node_modules
command: npm start
# Nginx Reverse Proxy
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
depends_on:
- api
- frontend
volumes:
postgres_data:
redis_data:Development with Hot Reload
version: '3.8'
services:
app:
build:
context: .
target: development
volumes:
# Mount source code
- .:/app
# Prevent overwriting node_modules
- /app/node_modules
environment:
NODE_ENV: development
ports:
- "3000:3000"
command: npm run devDatabase with Initialization
version: '3.8'
services:
db:
image: postgres:15
volumes:
- postgres_data:/var/lib/postgresql/data
# Mount initialization scripts
- ./init-scripts:/docker-entrypoint-initdb.d
environment:
POSTGRES_DB: myapp
POSTGRES_USER: dbuser
POSTGRES_PASSWORD: dbpass
volumes:
postgres_data:Useful Commands
Development Workflow
# Start development environment
docker compose up -d
# View logs for specific service
docker compose logs -f web
# Rebuild after changes
docker compose up -d --build
# Run tests
docker compose run --rm web npm test
# Access database
docker compose exec db psql -U dbuser -d myapp
# Clean up everything
docker compose down -v --remove-orphansProduction Workflow
# Build production images
docker compose -f docker-compose.prod.yml build
# Start production environment
docker compose -f docker-compose.prod.yml up -d
# Scale a service
docker compose -f docker-compose.prod.yml up -d --scale web=3
# Update a service
docker compose -f docker-compose.prod.yml up -d --no-deps --build webDebugging
# Inspect a service
docker compose ps web
# Check service configuration
docker compose config
# View container processes
docker compose top
# Execute command in container
docker compose exec web sh
# Copy files from container
docker compose cp web:/app/logs ./logsEnvironment-Specific Configs
Base Configuration
# docker-compose.yml
version: '3.8'
services:
web:
image: myapp:latest
environment:
NODE_ENV: productionDevelopment Override
# docker-compose.override.yml
version: '3.8'
services:
web:
build: .
volumes:
- .:/app
environment:
NODE_ENV: development
command: npm run devProduction Configuration
# docker-compose.prod.yml
version: '3.8'
services:
web:
image: myapp:${VERSION:-latest}
restart: always
deploy:
replicas: 3
resources:
limits:
cpus: '0.5'
memory: 512MUsage:
# Development (uses docker-compose.yml + docker-compose.override.yml)
docker compose up
# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -dTips and Best Practices
1. Use Environment Variables
services:
db:
image: postgres:${POSTGRES_VERSION:-15}
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}2. Optimize Build Context
services:
web:
build:
context: .
dockerfile: Dockerfile
# Only include necessary files
args:
- BUILD_DATE
- VERSION3. Use Named Volumes for Data
volumes:
database_data:
name: my_app_database
external: false4. Health Checks for Dependencies
services:
web:
depends_on:
db:
condition: service_healthy5. Resource Limits in Production
services:
web:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M6. Secure Secrets Management
# Use Docker secrets (Swarm mode)
docker secret create db_password ./db_password.txtservices:
db:
secrets:
- db_password
secrets:
db_password:
external: trueTroubleshooting
Common Issues
Port already in use:
# Find process using port
lsof -i :8000
# Kill process or change port mappingPermission denied:
services:
web:
user: "${UID}:${GID}"Containers can't communicate:
# Check network
docker network ls
docker network inspect myapp_defaultService won't start:
# Check logs
docker compose logs service_name
# Check configuration
docker compose configAdditional Resources
- Docker Compose Documentation
- Compose File Specification
- Docker Hub - Find official images
- Awesome Docker Compose - Example configurations
- Docker Compose Best Practices
Happy Containerizing! 🐳

Written by Robin te Hofstee
Technology enthusiast with a deep love for programming. Sharing practical guides on React, Next.js, Linux and self-hosting.
Related Posts
Securing a Next.js Application in Production
Securing a Next.js app in production means protecting the client bundle, the server, and the data flow. This post shows how to lock down Content‑Secur
How Git Works
Git is a distributed version control system that allows multiple people to collaborate on a project while maintaining a complete history of all change
How to Check Disk Usage and Find Large Files on Linux
After setting up a new Linux server, you’ll want to know how to check what’s taking up space. Disk space is often the weakest link in system stability


