docker compose up -d starts services in the background, but it returns immediately — before services are actually ready. --wait solves this by blocking until all services are healthy.
The problem
Without --wait, you often end up with fragile sleep-based scripts:
# Fragile: how long is enough?
docker compose up -d
sleep 10
npm test
The solution
docker compose up --wait
npm test
--wait starts services in detached mode and blocks until every service with a healthcheck reports healthy. If a service fails to become healthy, the command exits with a non-zero status.
It requires healthchecks
--wait relies on healthchecks to know when services are ready. Services without healthchecks are considered ready immediately after starting:
services:
postgres:
image: postgres:16
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
healthcheck:
test: ["CMD", "pg_isready"]
interval: 5s
timeout: 3s
retries: 5
redis:
image: redis:7
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
app:
image: myapp
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
interval: 5s
timeout: 3s
retries: 5
# Blocks until postgres, redis, AND app are all healthy
docker compose up --wait
Setting a timeout
Use --wait-timeout to avoid waiting forever if something goes wrong:
# Wait up to 60 seconds, then fail
docker compose up --wait --wait-timeout 60
This is essential in CI where you don’t want a broken service to hang the pipeline indefinitely.
CI pipeline example
A typical CI workflow:
# Start the full stack and wait for health
docker compose up --wait --wait-timeout 120
# Run tests against the healthy stack
docker compose exec app npm test
# Tear down
docker compose down
No sleep, no polling, no flaky timing issues. The stack is guaranteed to be healthy before tests run.
Combining with –exit-code-from
For test services that should run and exit, combine with --exit-code-from:
services:
postgres:
image: postgres:16
healthcheck:
test: ["CMD", "pg_isready"]
interval: 5s
tests:
image: myapp-tests
depends_on:
postgres:
condition: service_healthy
command: npm test
# Start postgres, wait for health, run tests, return test exit code
docker compose up --exit-code-from tests
echo $? # 0 if tests passed, non-zero otherwise