Compose applications

Add health and startup handling

Distinguish process startup from service readiness and make the API tolerate a database that is still initializing.

8 minute lesson

~~~

A running database container may still be replaying logs or creating its first database. Process state alone does not mean the service is ready.

A health check tests useful behavior. Compose can wait for a dependency to become healthy, but the application should still retry temporary connection failures because services can restart after initial startup.

database:
  healthcheck:
    test: ["CMD-SHELL", "pg_isready -U notes -d notes"]
    interval: 5s
    timeout: 3s
    retries: 10
api:
  depends_on:
    database:
      condition: service_healthy

The health command runs inside the database container, so it must use tools available in that image and test the same behavior the application needs. Keep it fast, read-only, and specific. A check that always succeeds proves nothing; a heavyweight check can create its own outage.

Use docker inspect to see recent probe results when a service remains unhealthy:

docker inspect database --format '{{json .State.Health}}'

Startup ordering is only an initial convenience. Connections can fail after both services are healthy, so the API still needs bounded retries with backoff, useful logs, and a clear terminal failure. Health checks should expose a problem, not replace application resilience.

Add the health check, recreate the stack, and watch docker compose ps while PostgreSQL changes from starting to healthy.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →