Lifecycle & Scaling
The core lifecycle commands
Section titled “The core lifecycle commands”Once you have a compose.yaml, these six commands cover day-to-day operations.
docker compose up
Section titled “docker compose up”Start all services defined in compose.yaml. Press Ctrl-C to stop.
docker compose upStart in the background (detached mode):
docker compose up -dRebuild images before starting (useful after changing a Dockerfile):
docker compose up -d --builddocker compose down
Section titled “docker compose down”Stop and remove containers and the default network. Named volumes are kept.
docker compose downAlso remove named volumes:
docker compose down -vdocker compose logs
Section titled “docker compose logs”Stream logs from all services:
docker compose logs -fStream logs from a specific service:
docker compose logs -f appdocker compose ps
Section titled “docker compose ps”List running containers for the current project:
docker compose psdocker compose build
Section titled “docker compose build”Build or rebuild images for services that use build::
docker compose buildBuild a specific service:
docker compose build appdocker compose exec
Section titled “docker compose exec”Run a command inside a running service container:
docker compose exec app shScaling services
Section titled “Scaling services”Run multiple replicas of a stateless service with --scale:
docker compose up -d --scale worker=3This starts three containers for the worker service. Each replica gets a unique name such as project-worker-1, project-worker-2, project-worker-3.
Important constraints on scaled services:
- Do not use a fixed
container_name:— Compose cannot give three containers the same name. - Do not use host-port mappings on a scaled service — you cannot bind the same host port to three containers.
A scalable service definition:
services: worker: image: myapp:latest # No container_name — Compose auto-names replicas # No ports — no host-port binding on scaled services environment: - QUEUE_URL=amqp://rabbitUnderstanding down vs down -v
Section titled “Understanding down vs down -v”docker compose down stops containers + removes containers + removes networksdocker compose down -v same as above + removes named volumesNamed volumes hold your database data, uploaded files, and caches. Only pass -v when you deliberately want to wipe that data — for example, when resetting a development database to a clean state.
Full lifecycle in practice
Section titled “Full lifecycle in practice”# Build imagesdocker compose build
# Start everything detacheddocker compose up -d
# Watch logsdocker compose logs -f
# Check statusdocker compose ps
# Scale the worker updocker compose up -d --scale worker=3
# Shut down (keep volumes)docker compose down
# Full reset — destroy volumes toodocker compose down -vHands-on practice
Section titled “Hands-on practice”# Create a compose.yaml with a scalable worker
cat > compose.yaml <<'EOF'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
worker:
image: alpine
command: >
sh -c "echo Worker $$HOSTNAME started && sleep 20"
EOF
# Start in detached mode
docker compose up -d
# Show running containers
docker compose ps
# Scale workers to 3
docker compose up -d --scale worker=3
# Show all containers (1 web + 3 workers)
docker compose ps
# Stream logs from all workers
docker compose logs worker
# Tear down (containers + network, volumes kept)
docker compose down
echo "All containers removed. Named volumes (if any) are still intact."Trade-offs
Section titled “Trade-offs”| Option | Benefit | Cost |
|---|---|---|
docker compose --scale | Scales a service horizontally fast, test load on a single dev machine right away | Limited to one host, no auto-scaling or self-healing across nodes |
| Kubernetes Deployment/HPA | Scales across many nodes automatically based on load, with self-healing | Requires setting up a cluster and controllers, and a much more complex operational model |
Common mistakes
Section titled “Common mistakes”- Using
depends_on: - dband assuming Compose waits until the database is actually ready to accept connections, when it only waits for the container to start — addhealthcheckandcondition: service_healthyif you need real readiness. - Running
docker compose up -d --scale db=3on a stateful service like a database, when the image was never designed to run multiple instances at once (leading to data corruption or port conflicts). - Forgetting that
docker compose down -vdeletes named volumes with no undo, and running it without checking which environment it’s pointed at first.
💡 Real-world example
Many platform teams use
docker compose up -d --scale worker=Nto test how a stateless worker behaves when scaled on a dev machine first, then move the same pattern to Kubernetesreplicasand aHorizontalPodAutoscalerin production, where they actually need to scale across multiple real machines.