Docker Compose cheat sheet

Docker Compose defines a multi-container application in one declarative file — by default compose.yaml — and starts the whole stack with a single command. Where docker run is one container, Compose is many, wired together with shared networks and volumes.

The modern command is docker compose (no hyphen), the Compose V2 plugin that ships with current Docker Desktop and Engine. The old docker-compose (V1) standalone is deprecated and missing newer features, so everything here uses the plugin form.

Published

The compose.yaml file

A two-service app: a web service and its database
services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

  web:
    build: .
    ports:
      - "8080:3000"
    environment:
      DATABASE_URL: postgres://db:5432/app
    depends_on:
      - db

volumes:
  pgdata:

The keys that matter

services:
the containers to run — one entry per service, names become DNS hostnames on the shared network
build: .
build an image from a Dockerfile in the given directory (vs image: which pulls one)
image: postgres:16
pull and run a pre-built image
ports: "8080:3000"
publish host:container ports, same as -p
volumes: - pgdata:/var/lib/...
named volume mounts, same as -v
environment:
environment variables (a map, or - KEY=value list form)
depends_on:
start this service only after the listed ones (ordering, not readiness)
Compose v2 no longer needs a top-level version: field — it was an obsolete Compose V1-era key and modern versions ignore it. Services reach each other by service name (db, web) over the project's default network, which is why the connection string above uses db:5432 instead of localhost. Note that depends_on only orders startup; for true "wait until ready" you need a healthcheck plus depends_on: condition: service_healthy.

The docker compose commands

The compose command set — all run in the directory containing compose.yaml
CommandWhat it does
docker compose up -dcreate and start the whole stack, detached (add --build to rebuild images first)
docker compose downstop and remove the stack (add -v to also delete named volumes)
docker compose pslist the stack's containers and their state
docker compose logs -f webfollow logs for one service (omit the name for all)
docker compose exec web bashopen a shell inside a service container
docker compose buildbuild/rebuild the images defined with build:
docker compose restart webrestart one service
docker compose pullpull the latest images without starting anything

One-off and admin tasks

Run commands without starting the whole stack
# Run a one-off command in a fresh container of a service
docker compose run --rm web npm run migrate

# Check the config and expand variables without running anything
docker compose config

# Show resource usage for the stack
docker compose stats

# Stop everything but keep the containers (down removes them)
docker compose stop

References

FAQ

What is the difference between docker compose and docker-compose?

docker compose (no hyphen) is the Compose V2 plugin, part of current Docker Desktop and Engine, and the actively developed implementation. docker-compose is the older V1 standalone Python binary, now deprecated. They run the same compose files for everyday use, but new features, the removal of the version field, and bug fixes are only in V2, so use docker compose.

How do I rebuild and restart my stack?

docker compose up -d --build rebuilds images where the build context changed and recreates only the affected containers, leaving unchanged services running. To also pick up a changed image tag for an image: service, add docker compose pull first. A full reset is docker compose down followed by up.

What does docker compose down -v do?

down stops and removes the stack's containers and networks; adding -v also deletes the named volumes declared in the file. Because volumes hold the persistent data, -v is destructive — leave it off if you want to keep database data between restarts.

How do services find each other in Compose?

Compose creates a default network and puts every service on it, with DNS entries matching the service names. A service named db is reachable from web as the hostname db on the container's port. No ports: mapping is needed for service-to-service traffic — ports: is only for exposing a service to the host.