Gate Compose Services on Health
Add healthchecks and depends_on conditions so services that need a database wait for it to be healthy, not merely started.
Task
Make docker compose wait for dependencies to be healthy before starting dependents.
When to use this
A service starts as soon as its database container is created, not ready, so it crashes on the first connection and restart loops.
Prerequisites
- Docker Compose v2
- A healthcheck command for each dependency
Steps
1. Add a healthcheck to the database and other dependencies.
Expected output: Readiness is observable, not assumed.
2. Use depends_on with condition service_healthy for dependents.
Expected output: Dependents start only after readiness.
3. Make the healthcheck a real probe, not just a listening port.
Expected output: The check reflects actual readiness.
4. Verify a cold start brings services up in order without restarts.
docker compose up --waitExpected output: Startup is reliable.
Troubleshooting
Problem
Healthcheck always failing
Solution
Check the probe command and start_period; a slow-starting dependency needs a longer start_period, not a weaker probe.
Problem
Circular startup
Solution
Keep dependency direction one way; a service should not depend on something that depends on it.
Limitations
- Compose health gating applies to local and simple environments; production orchestration uses its own readiness model.
- A healthcheck adds startup latency and can hide an application that is listening but not truly ready.
Context
Make docker compose wait for dependencies to be healthy before starting dependents. A service starts as soon as its database container is created, not ready, so it crashes on the first connection and restart loops.
Steps
- Add a healthcheck to the database and other dependencies. Expected: Readiness is observable, not assumed.
- Use depends_on with condition service_healthy for dependents. Expected: Dependents start only after readiness.
- Make the healthcheck a real probe, not just a listening port. Expected: The check reflects actual readiness.
- Verify a cold start brings services up in order without restarts. Expected: Startup is reliable.
services:
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 5s
retries: 10
api:
build: .
depends_on:
db: { condition: service_healthy }
Verify
- Readiness is observable, not assumed.
- Dependents start only after readiness.
- The check reflects actual readiness.
- Startup is reliable.
Limits
- Compose health gating applies to local and simple environments; production orchestration uses its own readiness model.
- A healthcheck adds startup latency and can hide an application that is listening but not truly ready.