While EXPOSE and STOPSIGNAL are self-explanatory, let’s look at the HEALTHCHECK directive. The HEALTHCHECK directive runs a command (hence CMD) called curl -f localhost. So, this container will report itself as healthy until the result of the curl command is a success.

The HEALTHCHECK directive also contains the following optional fields:

  • –interval (default: 30s): The interval between two subsequent health checks.
  • –timeout (default: 30s): The health check probe timeout. If the health check times out, it implies a health check failure.
  • –start-period (default: 0s): The time lag between starting the container and the first health check. This allows you to ensure your container is up before a health check.
  • –retries (default: 3): The number of times the probe will retry before declaring an unhealthy status.

Now, let’s build this container:

$ docker build -t <your_dockerhub_user>/nginx-hello-world .

[+] Building 1.3s (10/10) FINISHED

=> [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 334B 0.0s => [internal] load .dockerignore 0.0s

=> => transferring context: 2B 0.0s

=> [internal] load metadata for docker.io/library/ubuntu:bionic 1.2s => [1/5] FROM docker.io/library/ubuntu:bionic@sha256:152dc0… 0.0s => [internal] load build context 0.0s => => transferring context: 31B 0.0s

=> CACHED [2/5] RUN apt update && apt install -y curl 0.0s => CACHED [3/5] RUN apt update && apt install -y nginx 0s => CACHED [4/5] WORKDIR /var/www/html/ 0.0s => CACHED [5/5] ADD index.html ./ 0.0s

=> exporting to image 0.0s

=> => exporting layers 0.0s

=> => writing image sha256:bba3123d… 0.0s

=> => naming to docker.io/<your_dockerhub_user>/nginx-hello-world

It’s time to run it and see for ourselves:

$ docker run -d -p 80:80 <your_dockerhub_user>/nginx-hello-world 94cbf3fdd7ff1765c92c81a4d540df3b4dbe1bd9748c91e2ddf565d8…

Now that we have successfully launched the container, let’s try ps and see what we get:

$ docker ps      
CONTAINER IDIMAGECOMMANDCREATEDSTATUSPORTSNAMES
94cbf3fdd7ff<your_dockerhub“nginx -g5 secondsUp 40.0.0.0:80->80/wonderful_
 _user>/nginx-‘daemon of…”ago(health:tcp, :::80->80/tcphodgkin
 hello-world  starting)  

As we can see, the container shows health: starting, which means the health check hasn’t been started yet, and we are waiting for the start time to expire.

Let’s wait a while and then try docker ps again:

$ docker ps      
CONTAINER IDIMAGECOMMANDCREATEDSTATUSPORTSNAMES
94cbf3fdd7ff<your_dockerhub“nginx -g2 minutesUp 20.0.0.0:80->80/wonderful_
 _user>/nginx-‘daemon of…”ago(healthy)tcp, :::80->80/tcphodgkin
 hello-world     

This time, it reports the container as healthy. So, our container is now more reliable, as anyone monitoring it will know what part of the application is healthy and what part is not.

This health check only reports on the container’s health status. It takes no action beyond that. You are responsible for periodically monitoring the containers and writing a script to action unhealthy containers.

One way to manage this would be to create a script that checks for unhealthy containers and restarts them. You can schedule such a script in your crontab. You can also create a long-running systemd script that continuously polls the container processes and checks for the health status.

Tip

While using HEALTHCHECK is a great option, you should avoid using it to run your containers on Kubernetes or a similar container orchestrator. You should make use of liveness and readiness probes instead. Similarly, you can define health checks on Docker Compose if you are using it, so use that instead of baking the health check into the container image.

Now, let’s go ahead and learn how to build and manage Docker images.

Leave a Reply

Your email address will not be published. Required fields are marked *