Docker Compose Cheat Sheet
Docker Compose is part of my daily workflow. Here's an overview of the commands and configuration options I actually use.
The basics
Start all services defined in your compose.yaml:
docker compose up
Run in the background (detached mode):
docker compose up -d
Stop and remove containers:
docker compose down
Want to remove volumes too? Add -v:
docker compose down -v
Building images
Build images before starting:
docker compose up --build
Just build, don't start:
docker compose build
Force a rebuild without cache:
docker compose build --no-cache
Working with services
Start a specific service:
docker compose up -d postgres
Stop a specific service:
docker compose stop postgres
Restart a service:
docker compose restart postgres
View logs:
docker compose logs
Follow logs in real-time:
docker compose logs -f
Logs for a specific service:
docker compose logs -f postgres
Running commands
Execute a command in a running container:
docker compose exec app bash
Run a one-off command (starts a new container):
docker compose run --rm app php bin/console cache:clear
The --rm flag removes the container after the command finishes. You'll want this most of the time.
A practical compose.yaml
Here's a setup I use for Symfony projects:
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/var/www/html
ports:
- "8080:80"
depends_on:
postgres:
condition: service_healthy
environment:
DATABASE_URL: postgresql://app:secret@postgres:5432/app
postgres:
image: postgres:18-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
POSTGRES_DB: app
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:8-alpine
ports:
- "6379:6379"
mailpit:
image: axllent/mailpit
ports:
- "1025:1025"
- "8025:8025"
volumes:
postgres_data:
Environment variables
Use a .env file in the same directory as your compose.yaml:
POSTGRES_PASSWORD=secret
APP_DEBUG=true
Reference them in your compose file:
services:
postgres:
image: postgres:18-alpine
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
Or load an entire env file into a container:
services:
app:
image: my-app
env_file:
- .env
- .env.local
Healthchecks
Don't just use depends_on. Your database container might be running, but Postgres itself isn't ready yet. Use healthchecks:
services:
postgres:
image: postgres:18-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 5s
timeout: 5s
retries: 5
app:
depends_on:
postgres:
condition: service_healthy
Now app waits until Postgres actually accepts connections.
Volumes
Named volumes persist data:
services:
postgres:
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Bind mounts for development:
services:
app:
volumes:
- .:/var/www/html
- /var/www/html/vendor
That second line creates an anonymous volume for vendor, so it won't sync with your host. Useful when dependencies differ between your host and container.
Networks
By default, Compose creates a network for your project. All services can reach each other by their service name.
Need a custom network?
services:
app:
networks:
- frontend
- backend
postgres:
networks:
- backend
networks:
frontend:
backend:
Now postgres isn't reachable from frontend.
Multiple compose files
Override settings for different environments:
docker compose -f compose.yaml -f compose.prod.yaml up -d
The second file overrides or extends the first.
Or use compose.override.yaml. Compose picks this up automatically:
compose.yaml # Base configuration
compose.override.yaml # Local development overrides (auto-loaded)
Profiles
Define services that only run when you need them:
services:
app:
image: my-app
debug:
image: busybox
profiles:
- debug
The debug service won't start with docker compose up. Enable it explicitly:
docker compose --profile debug up
Scaling services
Run multiple instances of a service:
docker compose up -d --scale worker=3
This starts 3 containers for the worker service. Don't define a host port when scaling, or you'll get port conflicts.
Useful commands I always forget
See running containers:
docker compose ps
See all containers (including stopped):
docker compose ps -a
View resource usage:
docker compose top
Pull latest images:
docker compose pull
Remove stopped containers:
docker compose rm
Nuclear option (remove everything, including volumes and images):
docker compose down -v --rmi all
Quick reference
| Command | What it does |
|---|---|
up -d | Start in background |
down | Stop and remove |
down -v | Stop, remove, and delete volumes |
logs -f | Follow logs |
exec app bash | Shell into running container |
run --rm app cmd | Run one-off command |
build --no-cache | Rebuild from scratch |
ps | List containers |
pull | Update images |