Compose Basics
This page is a hands-on tour of the Compose CLI and file: bringing up a stack, inspecting it, wiring services together, and persisting data.
Prerequisites
- Docker Engine 29.x with the Compose v2 plugin (bundled with Docker Desktop and modern Docker Engine installs).
- Verify with
docker compose version. You should see v2.x, not the legacydocker-composev1 binary. - A working directory containing a
compose.yaml. Compose auto-detects it.
# Debian/Ubuntu, if not already present
sudo apt-get update && sudo apt-get install docker-compose-plugin
docker compose versionBasic Examples
1. A minimal one-service file
The smallest useful Compose file declares a single service from an image.
services:
web:
image: nginx:1.27
ports:
- "8080:80"servicesis the top-level map of everything Compose runs.webis the service name and becomes its network hostname.imagepulls a prebuilt image; no build step needed.portsmaps host8080to container80asHOST:CONTAINER.
2. Bring the stack up and down
docker compose up reconciles your host to the file.
docker compose up -d # start in the background
docker compose ps # list this project's containers
docker compose down # stop and remove containers + network-ddetaches so your terminal stays free.psshows only the current project's services, not every container on the host.downremoves containers and the default network but keeps named volumes.
3. View logs and follow output
Logs are aggregated per project and per service.
docker compose logs -f # follow all services
docker compose logs -f web # follow one service-fstreams new lines as they arrive.- Naming a service scopes output to just that container.
- Each line is prefixed with the service name so interleaved logs stay readable.
4. Build an image from a Dockerfile
Swap image for build to build local source.
services:
api:
build: .
ports:
- "8080:8080"build: .uses the Dockerfile in the current directory.docker compose up --buildforces a rebuild before starting.- The resulting image is tagged for the project automatically.
5. Set environment variables
Configuration flows in through environment or an env file.
services:
api:
build: .
environment:
LOG_LEVEL: "info"
env_file:
- .envenvironmentsets values inline for the container.env_fileloads key/value pairs from a file, keeping secrets out of the committed YAML.- Inline values override those from the env file on conflict.
6. Connect two services by name
The default project network gives you DNS by service name.
services:
api:
build: .
environment:
REDIS_URL: "redis://cache:6379"
cache:
image: redis:7apireachescacheusing the hostnamecache, resolved on the shared network.- No IP addresses and no manual network config are required.
- Compose creates the network automatically and attaches both services.
7. Persist data with a named volume
Named volumes keep data across restarts.
services:
db:
image: postgres:17
environment:
POSTGRES_PASSWORD: secret
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:- The top-level
volumesblock declarespgdataas Docker-managed storage. - The service mounts it at Postgres's data directory.
docker compose downleaves the volume intact; add--volumesto delete it.
Intermediate Examples
8. Wait for dependencies to be healthy
depends_on orders startup; a healthcheck makes it wait for readiness.
services:
api:
build: .
depends_on:
db:
condition: service_healthy
db:
image: postgres:17
environment:
POSTGRES_PASSWORD: secret
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 5- Without a healthcheck,
depends_ononly guarantees start order, not that Postgres accepts connections. condition: service_healthymakes Compose block until the check passes.pg_isreadyis Postgres's own readiness probe, ideal for this.
9. Run one-off commands against the stack
run and exec target services for tasks and debugging.
docker compose run --rm api npm test # one-off container for tests
docker compose exec db psql -U postgres # shell into a running containerrunstarts a fresh container for the command;--rmcleans it up after.execattaches to an already running service.- Both reuse the service's image, environment, and network.
10. Scale a stateless service
Stateless services can run multiple replicas on one host.
docker compose up -d --scale worker=3
docker compose ps--scale worker=3runs three instances of theworkerservice.- Do not scale a service that binds a fixed host port, since the port would collide.
- This is single-host scaling only; true multi-host scaling belongs to Kubernetes.
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).