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.
Search across all documentation pages
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.
docker compose version. You should see v2.x, not the legacy docker-compose v1 binary.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 versionThe smallest useful Compose file declares a single service from an image.
services:
web:
image: nginx:1.27
ports:
- "8080:80"services is the top-level map of everything Compose runs.web is the service name and becomes its network hostname.image pulls a prebuilt image; no build step needed.ports maps host 8080 to container 80 as HOST:CONTAINER.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-d detaches so your terminal stays free.ps shows only the current project's services, not every container on the host.down removes containers and the default network but keeps named volumes.Logs are aggregated per project and per service.
docker compose logs -f # follow all services
docker compose logs -f web # follow one service-f streams new lines as they arrive.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 --build forces a rebuild before starting.Configuration flows in through environment or an env file.
services:
api:
build: .
environment:
LOG_LEVEL: "info"
env_file:
- .envenvironment sets values inline for the container.env_file loads key/value pairs from a file, keeping secrets out of the committed YAML.The default project network gives you DNS by service name.
services:
api:
build: .
environment:
REDIS_URL: "redis://cache:6379"
cache:
image: redis:7api reaches cache using the hostname cache, resolved on the shared network.Named volumes keep data across restarts.
services:
db:
image: postgres:17
environment:
POSTGRES_PASSWORD: secret
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:volumes block declares pgdata as Docker-managed storage.docker compose down leaves the volume intact; add --volumes to delete it.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: 5depends_on only guarantees start order, not that Postgres accepts connections.condition: service_healthy makes Compose block until the check passes.pg_isready is Postgres's own readiness probe, ideal for this.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 containerrun starts a fresh container for the command; --rm cleans it up after.exec attaches to an already running service.Stateless services can run multiple replicas on one host.
docker compose up -d --scale worker=3
docker compose ps--scale worker=3 runs three instances of the worker service.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).
Reviewed by Chris St. John·Last updated Jul 16, 2026