DockerVoici le neuvième volet de la formation Docker. Dans mon précédent article, nous avons abordé la nomenclature détaillée des images et les registres dans lesquels elles sont stockées. Aujourd’hui, nous allons faire un petit atelier pratique un peu plus amusant en construisant nos premières images à l’aide d’un Dockerfile.

Anatomie d’un Dockerfile

Nous avons déjà eu l’occasion de voir un Dockerfile. Voici un petit aperçu des instructions que nous pouvons y trouver :

  • FROM – indique l’image de départ sur laquelle on va se baser.
  • CMD – Définit la commande à exécuter lors du lancement de l’image. Peut également être utilisé pour définir l’argument par défaut de l’instruction ENTRYPOINT.
  • RUN – Exécute une commande pour contribuer à la construction de votre image.
  • EXPOSE – Ouvre un ou plusieurs ports du réseau.
  • VOLUME – Crée un point de montage.
  • COPY – Ajoute un fichier dans l’image.
  • LABEL – Ajoute des métadonnées à l’image dans un format clé/valeur.
  • ENV – Définit une variable d’environnement.
  • ENTRYPOINT – Détermine l’exécutable qui doit être lancé au démarrage du conteneur. Utilisez CMD pour passer des options à cet exécutable.

Prenons un Dockerfile pour illustrer la différence subtile entre les instructions ENTRYPOINT et CMD :

$ cat Dockerfile
FROM rockylinux:8
LABEL maintainer="Microlinux <info@microlinux.fr>"
ENTRYPOINT ["/usr/bin/ping"]
CMD ["www.docker.com"]
  • Nous utilisons l’image de Rocky Linux dans sa version 8 comme base pour notre image personnalisée.
  • La deuxième ligne est une instruction LABEL, avec une paire clé/valeur. Ici, la clé est maintainer, suivie d’un signe égal, puis de la valeur Microlinux <info@microlinux.fr> entre guillemets. Nous ajoutons simplement des métadonnées à notre image.
  • L’instruction ENTRYPOINT fait en sorte que le conteneur exécute la commande /usr/bin/ping au démarrage.
  • Notez que /usr/bin/ping est entouré de guillemets et de crochets. Le format utilisé ici est un tableau JSON.
  • L’instruction CMD utilise également un tableau JSON. Ici, nous fournissons www.docker.com comme argument à ENTRYPOINT.
  • Au final, la commande qui va être exécutée sera /usr/bin/ping www.docker.com.
  • Lorsque vous créez un Dockerfile, il vaut mieux le nommer Dockerfile.

La commande docker build permet de construire l’image :

$ docker build -t kikinovak/dockerping:latest .
...
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM rockylinux:8
 ---> 4e97feadb276
Step 2/4 : LABEL maintainer="Microlinux <info@microlinux.fr>"
 ---> Running in fa96b6bf89ec
Removing intermediate container fa96b6bf89ec
 ---> 8c7c9a5890ed
Step 3/4 : ENTRYPOINT ["/usr/bin/ping"]
 ---> Running in 03a597b595e0
Removing intermediate container 03a597b595e0
 ---> c08c948e7bd8
Step 4/4 : CMD ["www.docker.com"]
 ---> Running in 7051dabcfa6e
Removing intermediate container 7051dabcfa6e
 ---> b06be6abe1c9
Successfully built b06be6abe1c9
Successfully tagged kikinovak/dockerping:latest
  • L’option -t permet de spécifier un nom et un tag pour l’image.
  • Notez le format utilisé pour le nom de l’image : identifiant Docker + barre oblique + nom du dépôt + deux-points + tag.
  • Si vous ne fournissez pas de tag, la valeur latest est présumée. Nous explicitions cette information ici par souci de précision.
  • La commande docker build attend un chemin où elle pourra trouver un Dockerfile utilisé pour construire l’image. Le point . indique à docker build qu’il faut utiliser le Dockerfile dans le répertoire courant.

Vérifions si l’image est bien disponible :

$ docker image ls
REPOSITORY             TAG       IMAGE ID       CREATED         SIZE
kikinovak/dockerping   latest    b06be6abe1c9   6 minutes ago   197MB
rockylinux             8         4e97feadb276   5 weeks ago     197MB

Notez que nous avons deux images :

  • Dans un premier temps, Docker a téléchargé notre image de base rockylinux:8 qui correspond à l’instruction FROM de notre Dockerfile.
  • Ensuite, Docker a exécuté les commandes et les instructions de notre Dockerfile pour créer l’image kikinovak/dockerping.

Maintenant que j’ai mon image, je peux la publier sur Docker Hub. Pour ce faire, je dois d’abord m’authentifier avec mon identifiant Docker :

$ docker login
Authenticating with existing credentials...
...
Login Succeeded

À présent, je peux télécharger mon image sur Docker Hub :

$ docker push kikinovak/dockerping
Using default tag: latest
The push refers to repository [docker.io/kikinovak/dockerping]
b9674b668e06: Mounted from library/rockylinux
latest: digest: sha256:8fd30a6170de239ec761b42cc3a7b91412c0... size: 529

Je vérifie si mon image apparaît bien sur Docker Hub :

Docker ping

Je retourne dans ma console et je lance mon image :

$ docker run kikinovak/dockerping
PING d1syzps6kort6n.cloudfront.net (52.222.174.72) 56(84) bytes of data.
64 bytes from server-52-222-174-72.fra54.r.cloudfront.net (52.222.174.72):
icmp_seq=1 ttl=241 time=28.6 ms
64 bytes from server-52-222-174-72.fra54.r.cloudfront.net (52.222.174.72):
icmp_seq=2 ttl=241 time=28.4 ms
64 bytes from server-52-222-174-72.fra54.r.cloudfront.net (52.222.174.72):
icmp_seq=3 ttl=241 time=28.3 ms

Notre conteneur tourne et envoie une série de ping vers docker.com. Appuyez sur Ctrl+C pour l’arrêter.

Rappelons-nous le contenu du Dockerfile utilisé pour créer cette image :

ENTRYPOINT ["usr/bin/ping"]
CMD ["www.docker.com"]

La valeur par défaut de CMD peut être substituée en fournissant une option en ligne de commande :

$ docker run kikinovak/dockerping google.fr
PING google.fr (142.250.74.227) 56(84) bytes of data.
64 bytes from par10s40-in-f3.1e100.net (142.250.74.227): icmp_seq=1 ttl=118
time=19.9 ms
64 bytes from par10s40-in-f3.1e100.net (142.250.74.227): icmp_seq=2 ttl=118
time=19.8 ms
64 bytes from par10s40-in-f3.1e100.net (142.250.74.227): icmp_seq=3 ttl=118
time=19.10 ms

Dans l’exemple ci-dessus, la commande ping utilisée était déjà présente dans l’image de base. Or, dans certains cas, le ou les logiciels utilisés peuvent ne pas être présents dans l’image de départ. Si nous nous étions basés sur l’image de Debian, voici ce que nous aurions obtenu :

$ docker pull debian:latest
$ docker run -it --name debianping debian:latest
root@c098cce01e95:/# ping docker.com
bash: ping: command not found

Dans ce cas, nous pouvons très bien ajouter la ou les commandes en question. En l’occurrence :

root@c098cce01e95:/# apt update
...
root@c098cce01e95:/# apt install iputils-ping
...
root@c098cce01e95:/# which ping
/bin/ping
root@c098cce01e95:/# ping docker.com
PING docker.com (141.193.213.20) 56(84) bytes of data.
64 bytes from 141.193.213.20 (141.193.213.20): icmp_seq=1 ttl=57 time=21.6 ms
64 bytes from 141.193.213.20 (141.193.213.20): icmp_seq=2 ttl=57 time=21.2 ms
64 bytes from 141.193.213.20 (141.193.213.20): icmp_seq=3 ttl=57 time=21.7 ms

Voici le Dockerfile qui va nous permettre de réaliser cette opération :

$ cat Dockerfile
FROM debian:latest
LABEL maintainer="Microlinux <info@microlinux.fr>"
RUN apt-get update \
    && apt-get install -y iputils-ping \
    && apt-get clean
ENTRYPOINT ["usr/bin/ping"]
CMD ["www.docker.com"]
  • Debian utilise les gestionnaires de paquets apt et apt-get. Le premier est plutôt utilisé de manière interactive, alors que le second servira plutôt dans les scripts.
  • Nous regroupons toutes les commandes apt-get en une seule instruction RUN de manière à produire une seule couche par-dessus l’image de base.
  • Théoriquement nous pourrions très bien nous servir de plusieurs commandes RUN, mais chacune d’entre elles résulterait en une couche supplémentaire.
  • L’antislash \ en fin de ligne est simplement utilisé pour améliorer la lisibilité du Dockerfile.
  • La commande apt-get clean sert à supprimer les paquets téléchargés, ce qui nous permet de réduire la taille de l’image résultante.

Construisez et exécutez cette image :

$ docker build -t kikinovak/debianping .
...
$ docker run kikinovak/debianping
PING emzm5pam37e4.wpeproxy.com (141.193.213.20) 56(84) bytes of data.
64 bytes from 141.193.213.20 (141.193.213.20): icmp_seq=1 ttl=57 time=21.1 ms
64 bytes from 141.193.213.20 (141.193.213.20): icmp_seq=2 ttl=57 time=21.2 ms
64 bytes from 141.193.213.20 (141.193.213.20): icmp_seq=3 ttl=57 time=21.2 ms

Notre image fonctionne comme prévu, nous pouvons donc la publier sur Docker Hub :

$ docker push kikinovak/debianping
Using default tag: latest
The push refers to repository [docker.io/kikinovak/debianping]
cdb2a396502f: Pushed
61581d479298: Mounted from library/debian
latest: digest: sha256:8ea7476028d70b638e6bb17da7f33cf512b0fa556... size: 741

Exercice 1

  • Construisez un conteneur nettools:latest basé sur la dernière image de Debian, et qui comprend les commandes ping, traceroute et curl. Le shell Bash devra être lancé au démarrage du conteneur.
  • Lancez le conteneur nettools et invoquez successivement les commandes ping -c 3 google.fr, curl google.fr et traceroute google.fr.
  • Quittez le conteneur et faites un brin de ménage.

AstuceNe vous cassez pas trop la tête si vous ne saisissez pas encore la différence entre ENTRYPOINT et CMD. Utilisez simplement ce qui fonctionne dans le contexte donné.

Exercice 2

  • Lancez un conteneur nommé rockyvim basé sur Rocky Linux 8 et connectez-vous au shell Bash de ce conteneur.
  • Installez l’éditeur de texte Vim de manière interactive.
  • Lancez Vim pour vérifier si tout va bien.
  • Quittez le conteneur.
  • Construisez une image personnalisée rockyvim:8 basée sur Rocky Linux 8 et qui contient l’éditeur Vim.

Exercice 3

  • Connectez-vous à Docker Hub.
  • Publiez les deux images personnalisées nettools:latest et rockyvim:8 sur Docker Hub.

Lire la suite : Gérer les volumes


La rédaction de cette documentation demande du temps et des quantités significatives de café espresso. Vous appréciez ce blog ? Offrez un café au rédacteur en cliquant sur la tasse.

 

Catégories : Formation

0 commentaire

Laisser un commentaire

Emplacement de l’avatar

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *