Skip to content

Lifecycle & Scaling

Once you have a compose.yaml, these six commands cover day-to-day operations.

Start all services defined in compose.yaml. Press Ctrl-C to stop.

Terminal window
docker compose up

Start in the background (detached mode):

Terminal window
docker compose up -d

Rebuild images before starting (useful after changing a Dockerfile):

Terminal window
docker compose up -d --build

Stop and remove containers and the default network. Named volumes are kept.

Terminal window
docker compose down

Also remove named volumes:

Terminal window
docker compose down -v

Stream logs from all services:

Terminal window
docker compose logs -f

Stream logs from a specific service:

Terminal window
docker compose logs -f app

List running containers for the current project:

Terminal window
docker compose ps

Build or rebuild images for services that use build::

Terminal window
docker compose build

Build a specific service:

Terminal window
docker compose build app

Run a command inside a running service container:

Terminal window
docker compose exec app sh

Run multiple replicas of a stateless service with --scale:

Terminal window
docker compose up -d --scale worker=3

This 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://rabbit
docker compose down stops containers + removes containers + removes networks
docker compose down -v same as above + removes named volumes

Named 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.

Terminal window
# Build images
docker compose build
# Start everything detached
docker compose up -d
# Watch logs
docker compose logs -f
# Check status
docker compose ps
# Scale the worker up
docker compose up -d --scale worker=3
# Shut down (keep volumes)
docker compose down
# Full reset — destroy volumes too
docker compose down -v
# 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."
Which command starts services in detached (background) mode?
What does docker compose down -v do that docker compose down alone does not?
Which flag rebuilds images before starting services?
Why can a scaled service not use a host-port mapping like ports: - '8080:80'?