Knowing if your Docker service is running is important. A broken service can lead to a big incident! Use Docker health checks to avoid this!
Paul Knulst in Docker • Dec 20, 2021 • 5 min read
1. Introduction
A health check is exactly what they sound like - a way of checking the health of a resource. In the case of Docker, a health check is used to determine the health of a running container.
When a health check command is created, it defines how a container can be tested to see if it is working correctly. With no health check defined, Docker cannot know whether or not the services running within your container are actually started or not.
While working with Docker, two ways of defining a health check exist:
- Dockerfile
- Docker-Compose file.
I will cover only Docker-Compose Healthchecks within this article.
2. An example using Nginx
Let’s see how health checks work by using a simple Nginx web service. To create a very simple website we need three files:
A docker-compose.very-simple-web.yml, a Dockerfile, and an index.html:
version: '3.4'
services:
web:
image: very-simple-web
build:
context: ./
dockerfile: Dockerfile
ports:
- "80:80"
restart: unless-stopped
FROM nginx
COPY html /usr/share/nginx/html
<html>
<head>
<title>Hello World FTP</title>
</head>
<body>
Hello World
</body>
</html>
The three files must be saved in this structure
Now let’s create the service:
docker-compose up -d --build
If you open a web browser to localhost you should see “Hello World”
3. Why do we need a health check?
Well, in this special case normally we don't need any health check because we are just serving a simple website with Nginx. But in a production environment, it is possible that we run multiple processes that could crash.
In this case, we could use our website, but the Docker service will still be running even though we cannot access the website.
If this service is running within a Docker Swarm, the Swarm will still think everything is working correctly because the container is in a running state. This leads to a problem that the Swarm thinks everything is fine and will not restart the container so that it will be working again.
4. Configure a health check within the compose file
As an example, the docker-compose.very-simple-web.yml will be extended by a simple curl
based health check (will be explained later):
version: '3.4'
services:
web:
image: very-simple-web
build:
context: ./
dockerfile: Dockerfile
restart: unless-stopped
ports:
- "80:80"
healthcheck:
test: curl --fail http://localhost || exit 1
interval: 60s
retries: 5
start_period: 20s
timeout: 10s
The Docker Compose Healtcheck contains five properties:
- test: This property specifies the command that will be executed and is the health check of the container. This command HAS TO be available and working if everything is set up correctly.
- interval: This property specifies the number of seconds to initially wait before executing the health check and then the frequency at which subsequent health checks will be performed.
- timeout: This property specifies the number of seconds Docker awaits for your health check command to return an exit code before declaring it as failed.
- retries: This property specifies the number of consecutive health check failures required to declare the container as *unhealthy*.
- start_period: This property specifies the number of seconds your container needs to bootstrap. During this period, health checks with an exit code greater than zero won’t mark the container as unhealthy; however, a status code of 0 will mark the container as healthy.
Note that this health check is based on curl
. To use this health check you have to guarantee that curl
is installed within the image used for running the service.
If curl
is not available another often-used health check is based on wget
and can look like this:
wget --no-verbose --tries=1 --spider http://localhost || exit 1
Just replace the curl
command in the prior defined compose file.
5. Often used Docker health checks
5.1 WGET
healthcheck:
test: wget --no-verbose --tries=1 --spider http://localhost || exit 1
interval: 60s
retries: 5
start_period: 20s
timeout: 10s
5.2 CURL
healthcheck:
test: curl --fail http://localhost || exit 1
interval: 60s
retries: 5
start_period: 20s
timeout: 10s
5.3 What to do if CURL/WGET is not available?
If you use an image that doesn’t have curl
or wget
installed you need to install it. This can be achieved by adding an install command to your Dockerfile.
curl
RUN apk --update --no-cache add curl
wget
RUN apt-get update && apt-get install -y wget
But keep in mind that if you add curl
or wget
you could also add all the attack surfaces of those two tools.
A good workaround will be creating your own program which will then be included in the docker health check test command.
6. A custom health check
In comparison to curl
or wget
the custom health check gets over all the issues of using an external tool:
- You’re using the same runtime as your actual app, so there are no additional prerequisites for your health check that has to be installed
- You can decide which logic you want in your health check and it can stay private, so only the Docker platform can execute that code.
The downside is that you have to create and maintain a separate piece of code. But as this will be written in the same language as your app it should be much easier to achieve than developing a complex curl
or wget
command (If it is complex).
7. Closing Notes
I hope you learned that having your Docker container started does not necessarily mean that your application is running and works how it was designed. Docker health checks can be implemented quickly to identify possible bugs in your software before they become a real problem.
Next time you create a Docker-Compose file, consider adding a health check.
This article was originally published on my blog at https://www.paulsblog.dev/how-to-successfully-implement-a-healthcheck-in-docker-compose/
Feel free to connect with me on my personal blog, Medium, LinkedIn, Twitter, and GitHub.
Did you find this article valuable? Want to support the author? (... and support development of current and future tutorials!). You can sponsor me on Buy Me a Coffee or Ko-Fi. Furthermore, you can become a free or paid member by signing up to my website. See the contribute page for all (free or paid) ways to say thank you!
Photo by Online Marketing / Unsplash
Top comments (0)