How health checks work in Docker Compose

In this article we're going to take a detailed look at how we can manage health checks with Docker Compose.

Health checks are an effective way to manage containers within a Docker Compose context. When a container depends on another container in order to work properly, we usually specify a depends_on rule in the target container's block.

However, this rule doesn't mean that Docker is going to perform a check on the status of the container specified in this rule. Instead, it means that such a container will be started before the target container. In other words, it's just a way to define a sequential order when starting containers.

Suppose that our app depends on a database and the database must be ready to accept connections from our app. Here's an example of how we can use health checks in this scenario:

  db:
    image: postgres
    container_name: db
    environment:
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_NAME}
    ports:
      - "127.0.0.1:5432:5432"
    volumes:
      - dbdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "${DB_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5
  app:
    depends_on:
      db:
        condition: service_healthy
        

The healthcheck block has the following properties:

  1. test: The shell command that performs the test. In this specific case the command-line utility used to perform the task is built-in but in many other cases, for example if you need to use curl, the commad-line tool must be installed in the Dockerfile during the build phase of the container.
  2. interval: The interval, in seconds, between each test execution.
  3. timeout: The amount of time, in seconds, we have to wait before getting a response from the test.
  4. retries: How many times we need to run the same test if we get an error.

On our app container, the depends_on block specifies when this container must be started, namely when the db container reaches the Healthy status.

So if we run docker compose up -d, the whole process will be as follows:

  1. db starts and stays as Unhealthy until a test succeeds.
  2. app starts and stays as Created because db is still Unhealthy.
  3. A test succeeds and db becomes Healthy.
  4. Since now db is Healthy, app becomes Started and is actually started.

Conclusion

The procedure depicted above represents a normal flow in the process of starting containers in a Docker Compose context. In case of errors, the quickest way of solving startup problems is to look through the container's logs with the docker container logs container-id command to check why the container returns an Error state.

Back to top