Implémenter_un_healthcheck_dans_Dockerfile__english_

Implement a healthcheck in Dockerfile

Here we will create a Docker image implementing a Web server developed in Python and a healtheck that will check the state of the Docker container.

Let’s create a Python web server in the app.py file:

cat <<EOF> app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
    return 'Hello world'
if __name__ == '__main__':
    app.run(host='0.0.0.0')
EOF

This script uses Flask, which we have to declare in the requirements.txt file:

cat <<EOF> requirements.txt
Flask==0.12.2
EOF

Now let’s create a Dockerfile with a healthcheck on the URL http://localhost:5000/ :

  • running every 5 seconds,
  • with a timeout of 3 seconds,
  • with 3 re-tests.
cat <<EOF> Dockerfile
FROM python:3.6-alpine
COPY . /app
WORKDIR /app
RUN apk --no-cache add curl
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD curl --fail http://localhost:5000/ || exit 1
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
EOF

Let’s create the image Docker flask-healthcheck:

docker build -t flask-healthcheck .
Sending build context to Docker daemon     28MB
Step 1/7 : FROM python:3.6-alpine
 ---> 876b6a885b74
Step 2/7 : COPY . /app
 ---> 146d6b476038
Step 3/7 : WORKDIR /app
 ---> Running in 89efefdda152
Removing intermediate container 89efefdda152
 ---> 8f4b012c6426
Step 4/7 : RUN apk --no-cache add curl
 ---> Running in d875923c5afb
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz
(1/3) Installing nghttp2-libs (1.41.0-r0)
(2/3) Installing libcurl (7.69.1-r1)
(3/3) Installing curl (7.69.1-r1)
Executing busybox-1.31.1-r19.trigger
OK: 12 MiB in 37 packages
Removing intermediate container d875923c5afb
 ---> 7eb5fa96aee7
Step 5/7 : HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD curl --fail http://localhost:5000/ || exit 1
 ---> Running in d337c608ff47
Removing intermediate container d337c608ff47
 ---> 2163cc036d82
Step 6/7 : RUN pip install -r requirements.txt
 ---> Running in e79041d71417
Collecting Flask==0.12.2
  Downloading Flask-0.12.2-py2.py3-none-any.whl (83 kB)
Collecting click>=2.0
  Downloading click-7.1.2-py2.py3-none-any.whl (82 kB)
Collecting Jinja2>=2.4
  Downloading Jinja2-2.11.2-py2.py3-none-any.whl (125 kB)
Collecting Werkzeug>=0.7
  Downloading Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB)
Collecting itsdangerous>=0.21
  Downloading itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
Collecting MarkupSafe>=0.23
  Downloading MarkupSafe-1.1.1.tar.gz (19 kB)
Building wheels for collected packages: MarkupSafe
  Building wheel for MarkupSafe (setup.py): started
  Building wheel for MarkupSafe (setup.py): finished with status 'done'
  Created wheel for MarkupSafe: filename=MarkupSafe-1.1.1-py3-none-any.whl size=12627 sha256=3ac04f6f0c3dc5c631b4fabc21d4bf46d309754f56ac5fc13621a1bcc1de91ba
  Stored in directory: /root/.cache/pip/wheels/ca/85/2f/4c3a8ca6fb5eec7b43ec1e5666c7274dcdb86d6c32231aaa9d
Successfully built MarkupSafe
Installing collected packages: click, MarkupSafe, Jinja2, Werkzeug, itsdangerous, Flask
Successfully installed Flask-0.12.2 Jinja2-2.11.2 MarkupSafe-1.1.1 Werkzeug-1.0.1 click-7.1.2 itsdangerous-1.1.0
Removing intermediate container e79041d71417
 ---> bedd1b25461e
Step 7/7 : CMD ["python", "app.py"]
 ---> Running in f4294ea8e09a
Removing intermediate container f4294ea8e09a
 ---> ed85ee516eda
Successfully built ed85ee516eda
Successfully tagged flask-healthcheck:latest

Let’s create a flask-healthcheck container based on this image and exposing the 5000 port:

docker run --rm -d --name flask-healthcheck -p 5000:5000 flask-healthcheck
86ca560de375a45aaf71e1ece16eef3a6aa22144be85e3a5585ff7efcdd34b45

Let’s check the status (.State.Health).

Just after the launch, we get a starting state:

docker inspect --format='{{json .State.Health}}' flask-healthcheck
{"Status":"starting","FailingStreak":0,"Log":[]}

Let’s check that the web server responds:

curl http://localhost:5000
Hello world

After a short period of time, the condition of the container changes to ``
healthy`:

docker inspect --format='{{json .State.Health}}' flask-healthcheck
{"Status":"healthy","FailingStreak":0,"Log":[{"Start":"2020-11-16T16:55:55.243313874Z","End":"2020-11-16T16:55:55.354710574Z","ExitCode":0,"Output":"  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n                                 Dload  Upload   Total   Spent    Left  Speed\n\r  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0\r100    11  100    11    0     0   3666      0 --:--:-- --:--:-- --:--:--  3666\nHello world"}]}

The status is also visible when displaying the list of Docker containers:

docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                    PORTS                    NAMES
86ca560de375        flask-healthcheck   "python app.py"     17 seconds ago      Up 16 seconds (healthy)   0.0.0.0:5000->5000/tcp   flask-healthcheck

You now know how to implement a healthcheck within a Docker container.

Implémenter_un_healthcheck_dans_Dockerfile__french_

Implémenter un healthcheck dans Dockerfile

Nous allons ici créer une image Docker implémentant un serveur Web développé en Python ainsi qu’un healtheck qui va vérifier l’état du conteneur Docker.

Créons un serveur Web en Python dans le fichier app.py :

cat <<EOF> app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
    return 'Hello world'
if __name__ == '__main__':
    app.run(host='0.0.0.0')
EOF

Ce script utilise Flask, que nous devons déclarer dans le fichier requirements.txt :

cat <<EOF> requirements.txt
Flask==0.12.2
EOF

Créons maintenant un fichier Dockerfile avec un healthcheck sur l’URL http://localhost:5000/ :

  • s’exécutant toutes les 5 secondes,
  • avec un timeout de 3 secondes,
  • avec 3 ré-essais.
cat <<EOF> Dockerfile
FROM python:3.6-alpine
COPY . /app
WORKDIR /app
RUN apk --no-cache add curl
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD curl --fail http://localhost:5000/ || exit 1
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
EOF

Créons l’image Docker flask-healthcheck :

docker build -t flask-healthcheck .
Sending build context to Docker daemon     28MB
Step 1/7 : FROM python:3.6-alpine
 ---> 876b6a885b74
Step 2/7 : COPY . /app
 ---> 146d6b476038
Step 3/7 : WORKDIR /app
 ---> Running in 89efefdda152
Removing intermediate container 89efefdda152
 ---> 8f4b012c6426
Step 4/7 : RUN apk --no-cache add curl
 ---> Running in d875923c5afb
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz
(1/3) Installing nghttp2-libs (1.41.0-r0)
(2/3) Installing libcurl (7.69.1-r1)
(3/3) Installing curl (7.69.1-r1)
Executing busybox-1.31.1-r19.trigger
OK: 12 MiB in 37 packages
Removing intermediate container d875923c5afb
 ---> 7eb5fa96aee7
Step 5/7 : HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD curl --fail http://localhost:5000/ || exit 1
 ---> Running in d337c608ff47
Removing intermediate container d337c608ff47
 ---> 2163cc036d82
Step 6/7 : RUN pip install -r requirements.txt
 ---> Running in e79041d71417
Collecting Flask==0.12.2
  Downloading Flask-0.12.2-py2.py3-none-any.whl (83 kB)
Collecting click>=2.0
  Downloading click-7.1.2-py2.py3-none-any.whl (82 kB)
Collecting Jinja2>=2.4
  Downloading Jinja2-2.11.2-py2.py3-none-any.whl (125 kB)
Collecting Werkzeug>=0.7
  Downloading Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB)
Collecting itsdangerous>=0.21
  Downloading itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
Collecting MarkupSafe>=0.23
  Downloading MarkupSafe-1.1.1.tar.gz (19 kB)
Building wheels for collected packages: MarkupSafe
  Building wheel for MarkupSafe (setup.py): started
  Building wheel for MarkupSafe (setup.py): finished with status 'done'
  Created wheel for MarkupSafe: filename=MarkupSafe-1.1.1-py3-none-any.whl size=12627 sha256=3ac04f6f0c3dc5c631b4fabc21d4bf46d309754f56ac5fc13621a1bcc1de91ba
  Stored in directory: /root/.cache/pip/wheels/ca/85/2f/4c3a8ca6fb5eec7b43ec1e5666c7274dcdb86d6c32231aaa9d
Successfully built MarkupSafe
Installing collected packages: click, MarkupSafe, Jinja2, Werkzeug, itsdangerous, Flask
Successfully installed Flask-0.12.2 Jinja2-2.11.2 MarkupSafe-1.1.1 Werkzeug-1.0.1 click-7.1.2 itsdangerous-1.1.0
Removing intermediate container e79041d71417
 ---> bedd1b25461e
Step 7/7 : CMD ["python", "app.py"]
 ---> Running in f4294ea8e09a
Removing intermediate container f4294ea8e09a
 ---> ed85ee516eda
Successfully built ed85ee516eda
Successfully tagged flask-healthcheck:latest

Créons un conteneur flask-healthcheck basé sur cette image et exposant le port 5000 :

docker run --rm -d --name flask-healthcheck -p 5000:5000 flask-healthcheck
86ca560de375a45aaf71e1ece16eef3a6aa22144be85e3a5585ff7efcdd34b45

Vérifions l’état (.State.Health).

Juste après le lancement, on obtient un état starting :

docker inspect --format='{{json .State.Health}}' flask-healthcheck
{"Status":"starting","FailingStreak":0,"Log":[]}

Vérifions que le serveur Web répond :

curl http://localhost:5000
Hello world

Après un court délai, l’état du conteneur change en healthy :

docker inspect --format='{{json .State.Health}}' flask-healthcheck
{"Status":"healthy","FailingStreak":0,"Log":[{"Start":"2020-11-16T16:55:55.243313874Z","End":"2020-11-16T16:55:55.354710574Z","ExitCode":0,"Output":"  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n                                 Dload  Upload   Total   Spent    Left  Speed\n\r  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0\r100    11  100    11    0     0   3666      0 --:--:-- --:--:-- --:--:--  3666\nHello world"}]}

L’état est également visible quand on affiche la liste des conteneurs Docker :

docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                    PORTS                    NAMES
86ca560de375        flask-healthcheck   "python app.py"     17 seconds ago      Up 16 seconds (healthy)   0.0.0.0:5000->5000/tcp   flask-healthcheck

Vous savez maintenant implémenter un healthcheck au sein d’un conteneur Docker.

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×