services:
api:
build: .
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
environment: { POSTGRES_PASSWORD: example }
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 10
Plain depends_on only waits for the db container to start. It does not wait for Postgres inside the container to accept connections. Postgres needs a few seconds to start up, so the API connects too early and fails.
This file fixes it in two steps:
- It adds a
healthcheckthat runspg_isreadyevery 5 seconds. A healthcheck is a command Docker runs to test if the service works. condition: service_healthymakes Compose wait until that check passes. Only then does it startapi.
There are other conditions too:
service_startedis the default.service_completed_successfullywaits for a service to finish without errors. This is useful for a one-off job, like a database migration.
This only helps when Compose starts the services. Later, the database can still restart or drop connections. So the app should also retry its connection with backoff (waiting longer between each try). It should not assume the database is always up.
depends_onalone waits for the container to start, not for it to be ready.- Add a healthcheck to the service you depend on.
condition: service_healthywaits for the healthcheck to pass.- Use
service_completed_successfullyfor one-off jobs like migrations. - The app should still retry its database connections.
Read more