TP 2b - Exercices sur les images

Portainer :

Docker Hub

  • Avec docker login, docker tag et docker push, poussez l’image microblog sur le Docker Hub. Créez un compte sur le Docker Hub le cas échéant.
Solution :

L’instruction HEALTHCHECK

HEALTHCHECK permet de vérifier si l’app contenue dans un conteneur est en bonne santé.

  • Dans un nouveau dossier ou répertoire, créez un fichier Dockerfile dont le contenu est le suivant :
FROM python:alpine

RUN apk add curl
RUN pip install flask

ADD /app.py /app/app.py
WORKDIR /app
EXPOSE 5000

HEALTHCHECK CMD curl --fail http://localhost:5000/health

CMD python app.py
  • Créez aussi un fichier app.py avec ce contenu :
from flask import Flask

healthy = True

app = Flask(__name__)

@app.route('/health')
def health():
    global healthy

    if healthy:
        return 'OK', 200
    else:
        return 'NOT OK', 500

@app.route('/kill')
def kill():
    global healthy
    healthy = False
    return 'You have killed your app.', 200


if __name__ == "__main__":
    app.run(host="0.0.0.0")
  • Observez bien le code Python et la ligne HEALTHCHECK du Dockerfile puis lancez l’app. A l’aide de docker ps, relevez où Docker indique la santé de votre app.

  • Visitez l’URL /kill de votre app dans un navigateur. Refaites docker ps. Que s’est-il passé ?

  • (Facultatif) Rajoutez une instruction HEALTHCHECK au Dockerfile de notre app microblog.


Facultatif : construire une image “à la main”

Avec docker commit, trouvons comment ajouter une couche à une image existante. La commande docker diff peut aussi être utile.

Solution :

Facultatif : Décortiquer une image

Une image est composée de plusieurs layers empilés entre eux par le Docker Engine et de métadonnées.

  • Affichez la liste des images présentes dans votre Docker Engine.

  • Inspectez la dernière image que vous venez de créez (docker image --help pour trouver la commande)

  • Observez l’historique de construction de l’image avec docker image history <image>

  • Visitons en root (sudo su) le dossier /var/lib/docker/ sur l’hôte. En particulier, image/overlay2/layerdb/sha256/ :

    • On y trouve une sorte de base de données de tous les layers d’images avec leurs ancêtres.
    • Il s’agit d’une arborescence.
  • Vous pouvez aussi utiliser la commande docker save votre_image -o image.tar, et utiliser tar -C image_decompressee/ -xvf image.tar pour décompresser une image Docker puis explorer les différents layers de l’image.

  • Pour explorer la hiérarchie des images vous pouvez installer https://github.com/wagoodman/dive


Facultatif : un Registry privé

  • En récupérant la commande indiquée dans la doc officielle, créez votre propre registry.
  • Puis trouvez comment y pousser une image dessus.
  • Enfin, supprimez votre image en local et récupérez-la depuis votre registry.
Solution :

Facultatif : Faire parler la vache

Créons un nouveau Dockerfile qui permet de faire dire des choses à une vache grâce à la commande cowsay. Le but est de faire fonctionner notre programme dans un conteneur à partir de commandes de type :

  • docker run --rm cowsay Coucou !

  • docker run --rm cowsay doit afficher une vache qui dit “Hello”

  • docker run --rm cowsay -f stegosaurus Yo!

  • docker run --rm cowsay -f elephant-in-snake Un éléphant dans un boa.

  • Doit-on utiliser la commande ENTRYPOINT ou la commande CMD ? Se référer au manuel de référence sur les Dockerfiles si besoin.

  • Pour information, cowsay s’installe dans /usr/games/cowsay.

  • La liste des options (incontournables) de cowsay se trouve ici : https://debian-facile.org/doc:jeux:cowsay

Solution :
  • L’instruction ENTRYPOINT et la gestion des entrées-sorties des programmes dans les Dockerfiles peut être un peu capricieuse et il faut parfois avoir de bonnes notions de Bash et de Linux pour comprendre (et bien lire la documentation Docker).
  • On utilise parfois des conteneurs juste pour qu’ils s’exécutent une fois (pour récupérer le résultat dans la console, ou générer des fichiers). On utilise alors l’option --rm pour les supprimer dès qu’ils s’arrêtent.

Facultatif : TP avancé : Un multi-stage build avec distroless comme image de base de prod

Chercher la documentation sur les images distroless. Quel est l’intérêt ? Quels sont les cas d’usage ?

Objectif : transformer le Dockerfile de l’app nodejs (express) suivante en build multistage : https://github.com/Uptime-Formation/docker-example-nodejs-multistage-distroless.git Le builder sera par exemple basé sur l’image node:20 et le résultat sur gcr.io/distroless/nodejs20-debian11.

La doc:

Deux exemples simple pour vous aider:

Une correction possible dans la branche correction : git clone https://github.com/Uptime-Formation/docker-example-nodejs-multistage-distroless/ -b correction

L’image résultante fait tout de même environ 170Mo.

Pour entrer dans les détails de l’image on peut installer et utiliser https://github.com/wagoodman/dive