Aller au contenu

Construire une image de conteneur

Objectifs :

  • Construire une image à partir d'un Dockerfile

  • Publier cette image sur Docker Hub

Contenu 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 voir le rapport entre les instructions ENTRYPOINT et CMD :

$ cat Dockerfile
FROM rockylinux:latest
LABEL maintainer="Microlinux <info@microlinux.fr>"
ENTRYPOINT ["/usr/bin/ping"]
CMD ["www.docker.com"]
  • Nous utilisons la dernière image Rocky Linux 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:latest
 ---> c830f8e8f82b
Step 2/4 : LABEL maintainer="Microlinux <info@microlinux.fr>"
 ---> Running in ea304425eb7e
Removing intermediate container ea304425eb7e
 ---> 76ce20858571
Step 3/4 : ENTRYPOINT ["/usr/bin/ping"]
 ---> Running in 714f2f366b76
Removing intermediate container 714f2f366b76
 ---> f53922b2b819
Step 4/4 : CMD ["www.docker.com"]
 ---> Running in be1a6fbcbdb3
Removing intermediate container be1a6fbcbdb3
 ---> f2483023f694
Successfully built f2483023f694
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    f2483023f694   45 seconds ago   205MB
rockylinux             latest    c830f8e8f82b   9 days ago       205MB

Notez que nous avons deux images :

  • Dans un premier temps, Docker a téléchargé notre image de base, qui est rockylinux:latest, et 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 :

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 ["/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 ["/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
c9a63110150b: Mounted from kikinovak/dockerping
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.

Exercice 2

  • Lancez un conteneur nommé rockyvim basé sur Rocky Linux 8.5 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:latest basée sur Rocky Linux 8.5 et qui contient l'éditeur Vim.

Exercice 3

  • Connectez-vous à Docker Hub.

  • Publiez les deux images personnalisées nettools:latest et rockyvim:latest sur Docker Hub.


La rédaction de ces cours demande du temps et des quantités significatives de café espresso. Vous appréciez cette formation ? Offrez un café au formateur en cliquant sur la tasse.