• Modern UX

    Edit and navigate faster in the terminal with Warp's IDE-like input editor.

  • Warp AI

    AI suggests what commands to run and learns from your documentation.

  • Agent Mode

    Delegate tasks to AI and use natural language on the command line.

  • Warp Drive

    Save and share interactive notebooks, workflows, and environment variables.

  • All Features

Understand healthcheck in Docker Compose

Thumbnail for Gabriel ManricksGabriel Manricks

Gabriel Manricks

Chief Architect, ClearX

Published: 2/5/2024

About Terminus

In Docker Compose, a health check is a configuration option that allows you to define a command to periodically check the health of a container. This feature helps ensure that the container is not only running but also in a "healthy" state, meaning it's ready to handle requests or perform its intended functions.

The short answer

To define a health check for a specific service, you can specify the healthcheck  property within the service definition in the compose.yaml  file as follows:

 services:
  <service_name>:
    image: <image_name>
    healthcheck:
      test: <command>

Run in Warp

Where command  is the command that will be periodically executed by Compose to check whether the service is healthy or unhealthy. The container is considered healthy if the exit status of this command is 0 , and unhealthy otherwise.

For example, the following configuration checks whether the webserver  service is healthy by sending an HTTP request to the nginx  server located at the localhost address:

 services:
  webserver:
    image: nginx
    healthcheck:
      test: "curl -f http://localhost"

Run in Warp

Note that the -f  flag will cause the command to fail by returning a non-zero exit code if the HTTP request' status code represents an error (e.g. 500 ).

Easily retrieve this syntax using the Warp AI feature

If you’re using Warp as your terminal, you can easily retrieve this syntax using the Warp AI feature:

Thumbnail for

Entering docker compose health checks  in the AI question input will prompt a human-readable step-by-step guide, including code snippets.

Customizing the health check settings

By default, Docker will run the test command every 30 seconds, and it will give the command 30 seconds to complete before considering the health check failed. If the health check command fails 3 times in a row, the container is then considered "unhealthy".

To change these settings, you can use the following properties:

  • interval : the period between health checks (default 30s ).
  • timeout : the amount of time given to the command to complete (default 30s ).
  • retries : the number of consecutive fails before considered unhealthy (default 3 ).

For example:

 healthcheck: 
  test: "curl -f http://localhost"
  interval: 15s
  timeout: 1m
  retries: 2

Run in Warp

In some cases, you may have a container that takes a long time to initially start, which would cause the service to be considered unhealthy using the regular interval settings.

To change these settings, you can use the following properties:

  • start_period : the grace period during which Compose will not consider the health check failures (default 0s ). However, if the health check succeeds, then the container is marked healthy, and the grace period ends early.
  • start_interval : the period between health checks during the grace period (default 5s ).

For example:

 healthcheck: 
    test: "curl -f http://localhost"
    start_period: 1m
    start_interval: 10s

Run in Warp

Customizing the test command format

In Docker Compose, health check test commands can be executed using two different keywords: CMD  and CMD-SHELL .

Executing test commands using CMD

When using the CMD  form, the test command is split into multiple elements, where the first element is the command itself, and the subsequent elements are its options and arguments. In this form, the test command is executed directly without involving a shell.

For example:

 healthcheck: 
  test: ["CMD", "curl", "-f", "http://localhost"]

Run in Warp

Executing test commands using CMD-SHELL

When using the CMD-SHELL  form, the test command is specified as a single string. In this form, the test command is executed in a subshell, which allows you to leverage the shell's environment and features like variable substitution, pipes, or redirects.

For example:

 healthcheck:
  test: ["CMD-SHELL", "curl -f http://localhost"]

Run in Warp

Note that, in this form, the above command is equivalent to the following one:

healthcheck:
  test: "curl -f http://localhost"

Run in Warp

Managing dependencies with health checks

One of the main uses of health checks is to manage the dependencies between containers. For example, if you have a web server that depends on a MySQL server, you might need to make sure that the MySQL server is up and running before starting the web server.

This can be done using the depends_on  property, waiting for the condition service_healthy  as follows:

 services:
  mysql:
    image: mysql:8.2
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_USER: test
      MYSQL_PASSWORD: test
    healthcheck:
      test: "mysql --user=$$MYSQL_USER --password=$$MYSQL_PASSWORD --execute \"SHOW DATABASES;\" || exit 1"
      interval: 10s
      timeout: 10s
      retries: 5
      start_period: 20s
 test_site:
    image: nginx
    depends_on:
      mysql:
        condition: service_healthy

Run in Warp

In this example, there is a health check set on the MySQL service, which simply tries to execute a simple query to see if the DB is responding.

Under the test_site  service, there is the depends_on  field with a single dependency on the service named mysql  and a condition of service_healthy , which means when the service is marked healthy. Running this, you will see that at first, only the MySQL service will be started, and the test_site container will wait until MySQL is marked healthy to begin running.

To learn more about the dependencies between services in Docker Compose, you can read our in-depth article on how to use the depends_on field in Compose.

Viewing the status and logs of a health check

To view the status of the health checks along with the logs from each test, you can use the following docker inspect  command:

$ docker inspect --format='{{json .State.Health}}' <container_name_or_id>

Run in Warp

Where:

  • The docker inspect  command returns a JSON output with all the information about a specific container.
  • The --format  option extracts just the subfield in the JSON object with the health check info, which is located under the Health  key that is inside an object called State .

This output can be piped to a JSON parsing CLI like jq  or fx  to pretty print the JSON like in the following example:

 $ docker inspect --format "{{json .State.Health }}" test-docker-mysql-1 | jq

Run in Warp

Checking for a specific HTTP status code

To create a health check that checks for a specific HTTP status code, you can combine the curl  command to make a request and the grep  command to filter the result as follows:

 services:
  <service_name>:
    image: <image_name>
    healthcheck:
      test: "curl -s -I http://localhost | head -n 1 | grep 200"

Run in Warp

Where:

  • The curl -s -l  command is used to only print the response’s headers while avoiding printing the request’s progress or errors.
  • The head -n 1  command is used to only print the first line of the output generated by the curl  command.
  • The grep  command is used to verify that the filtered output includes the status code 200. If the line doesn’t include the specified code, it will return a non-zero exit code, triggering a failed health check.

Checking for an open TCP port

A basic health check that can be done on a variety of containers is to check if a TCP port is open and accepting connections.

Attempting a TCP connection with Netcat

If the container you want to perform a health check on has access to the nc  utility (short for Netcat), you can use the -z  flag to attempt a connection on a specified port without actually sending any data to it:

 healthcheck:
  test: ["CMD", "nc", "-z", "localhost", "5672"]

Run in Warp

Attempting a TCP connection with Bash

If the container you want to perform a health check on has access to the bash  utility, you can use the following command to write an empty string to a pseudo file in the /dev/tcp  directory, which will attempt a connection on the TCP socket identified by the specified ip_address  and port :

 healthcheck:
  test: ["CMD", "bash", "-c", "echo -n '' > /dev/tcp/<ip_address>/<port>"]

Run in Warp

Where:

  • The -c  option is used to tell bash  to execute a command.
  • The -n  option is used to tell echo  to write without appending a newline character.

For example, this command will attempt a TCP connection to the localhost identified by the IP address 127.0.0.1  and the port 5672 :

healthcheck:
  test: ["CMD", "bash", "-c", "echo -n '' > /dev/tcp/127.0.0.1/5672"]

Run in Warp

It is worth noting that even though this command uses a shell to run a command, you can’t use CMD-SHELL  as this feature doesn’t work in all shells (e.g. doesn’t work with sh) so you need to manually specify the use of bash .

Written by

Thumbnail for Gabriel ManricksGabriel Manricks

Gabriel Manricks

Chief Architect, ClearX

Filed Under

Related Articles

Override the Container Entrypoint With docker run

Learn how to override and customize the entrypoint of a Docker container using the docker run command.

Docker

The Dockerfile ARG Instruction

Learn how to define and set build-time variables for Docker images using the ARG instruction and the --build-arg flag.

Docker
Thumbnail for Razvan LudosanuRazvan Ludosanu

Start a Docker Container

Learn how to start a new Docker container from an image in both the foreground and the background using the docker-run command.

Docker
Thumbnail for Razvan LudosanuRazvan Ludosanu

Stop All Docker Containers

How to gracefully shutdown running containers and forcefully kill unresponsive containers with signals in Docker using the docker-stop and docker-kill commands.

Docker
Thumbnail for Razvan LudosanuRazvan Ludosanu

Use An .env File In Docker

Learn how to write and use .env files in Docker to populate the environment of containers on startup.

Docker

Run SSH In Docker

Learn how to launch and connect to a containerized SSH server in Docker using password-based authentication and SSH keys.

Docker
Thumbnail for Gabriel ManricksGabriel Manricks

Launch MySQL Using Docker Compose

Learn how to launch a MySQL container in Docker Compose.

DockerSQL

Execute in a Docker Container

Learn how to execute one or multiple commands in a Docker container using the docker exec command.

Docker
Thumbnail for Razvan LudosanuRazvan Ludosanu

Expose Docker Container Ports

Learn how to publish and expose Docker container ports using the docker run command and Dockerfiles.

Docker

Restart Containers In Docker Compose

Learn how to restart and rebuild one or more containers in Docker Compose.

Docker
Thumbnail for Razvan LudosanuRazvan Ludosanu

Output Logs in Docker Compose

Learn how to output, monitor, customize and filter the logs of the containers related to one or more services in Docker Compose

Docker
Thumbnail for Razvan LudosanuRazvan Ludosanu

Rename A Docker Image

Learn how to rename Docker images locally and remotely using the docker tag command.

Docker

Trusted by hundreds of thousands of professional developers

Download Warp to get started

Download for Mac
Thumbnail for null