Scaling Services

Scaling Services with the --scale Flag

docker compose up --scale api=3 runs three containers of one service, numbered -1, -2 and -3. A fixed host port stops the second one, because only one container can own a host port. A port range lets each replica take its own, and overriding API_PORT in the shell beats the .env file:

Three API replicas on a port range, then back to oneShell
docker compose up -d --scale api=3 2>&1 | grep -o 'Bind for.*allocated'
API_PORT=33000-33002 docker compose up -d --scale api=3 >/dev/null 2>&1
docker compose ps api --format '{{.Name}}  {{.Ports}}' | sed 's/, \[::\].*//'
for p in 33000 33001 33002; do curl -s localhost:$p/health; echo; done
docker compose exec db getent hosts api
docker compose up -d --scale api=1 >/dev/null 2>&1; docker compose ps --format '{{.Name}}'
Output
Bind for 0.0.0.0:33000 failed: port is already allocated
l3-booknest-api-1  0.0.0.0:33002->3000/tcp
l3-booknest-api-2  0.0.0.0:33000->3000/tcp
l3-booknest-api-3  0.0.0.0:33001->3000/tcp
{"status":"ok","version":"1.3"}
{"status":"ok","version":"1.3"}
{"status":"ok","version":"1.3"}
172.19.0.5      api
172.19.0.3      api
172.19.0.4      api
l3-booknest-api-1
l3-booknest-db-1

Inside the network the service name api now resolves to all three addresses, so Docker 514 's DNS spreads new connections across the replicas; a client that caches one address does not. container_name: fixes a container's name and therefore forbids scaling, which is one reason BookNest's file leaves names to Compose 514 . Scaling on one machine only adds processes on the same CPUs; spreading load across machines is the job of Swarm 514 (Docker Swarm in 2026) and Kubernetes 5,150 (Kubernetes).