Que sont les calques d’image Docker ?
Les images Docker se composent de plusieurs couches qui fournissent collectivement le contenu que vous voyez dans vos conteneurs. Mais qu’est-ce qu’un calque et en quoi diffère-t-il d’une image complète ?
Dans cet article, vous apprendrez à distinguer ces deux concepts et pourquoi la différence est importante. Bien que vous puissiez utiliser Docker sans une compréhension approfondie des couches, connaître leur objectif vous aidera à identifier les opportunités d’optimisation.
Sommaire
Qu’est-ce qu’une image ?
Une « image » Docker se comporte comme un modèle à partir duquel des conteneurs cohérents peuvent être créés. Si Docker était une machine virtuelle traditionnelle, l’image pourrait être assimilée à l’ISO utilisée pour installer votre machine virtuelle. Ce n’est pas une comparaison solide, car Docker diffère des machines virtuelles en termes de concept et de mise en œuvre, mais c’est néanmoins un point de départ utile.
Les images définissent l’état initial du système de fichiers des nouveaux conteneurs. Ils regroupent le code source de votre application et ses dépendances dans un package autonome prêt à être utilisé avec un environnement d’exécution de conteneur. Dans l’image, le contenu du système de fichiers est représenté sous forme de plusieurs couches indépendantes.
Que sont les calques ?
Les calques sont le résultat de la façon dont les images Docker sont construites. Chaque étape d’un Dockerfile crée une nouvelle « couche » qui est essentiellement un diff des modifications du système de fichiers depuis la dernière étape. Instructions de métadonnées telles que LABEL
et MAINTAINER
ne créez pas de couches car elles n’affectent pas le système de fichiers.
Cette image a deux instructions (COPY
et RUN
) donc ça va créer deux calques :
FROM ubuntu:latest
COPY foo.txt /foo.txt
RUN date > /built-on.txt
- La première étape copie
foo.txt
dans un nouveau calque basé surubuntu:latest
image. - La deuxième étape exécute le
date
commande et dirige sa sortie dans un fichier. Cela crée un deuxième calque basé sur le précédent.
Créer foo.txt
dans votre répertoire de travail :
$ echo "Hello World" > foo.txt
Créez maintenant l’exemple d’image :
$ docker build . -t demo:latest
Sending build context to Docker daemon 2.56kB
Step 1/3 : FROM ubuntu:latest
---> df5de72bdb3b
Step 2/3 : COPY foo.txt /foo.txt
---> 4932aede6a15
Step 3/3 : RUN date > /built-on.txt
---> Running in 91d260fc2e68
Removing intermediate container 91d260fc2e68
---> 6f653c6a60fa
Successfully built 6f653c6a60fa
Successfully tagged foo:latest
Chaque étape de construction émet l’ID de la couche créée. Le calque de la dernière étape devient l’image finale, il est donc étiqueté avec foo:latest
.
La séquence révèle que les calques sont des images Docker valides. Bien que le terme « calque » ne soit normalement pas utilisé pour désigner une image étiquetée, toutes les images étiquetées ne sont techniquement que des calques avec un identifiant attribué.
Vous pouvez démarrer un conteneur à partir de l’image d’une couche intermédiaire :
$ docker run -it 4932aede6a15 sh
# cat /foo.txt
Hello World
# cat /built-on.txt
cat: /built-on.txt: No such file or directory
Cet exemple démarre un conteneur à partir de la couche créée par la deuxième étape de génération. foo.txt
est disponible dans le conteneur mais built-on.txt
n’existe pas car il n’est ajouté qu’à la troisième étape. Ce fichier n’est disponible que dans les systèmes de fichiers des couches suivantes.
Le rôle des calques
Les couches contiennent les modifications créées par une étape de construction, par rapport à la couche précédente dans le Dockerfile. FROM
Les instructions sont un cas particulier qui fait référence à la couche finale d’une image existante.
Les couches permettent de mettre en cache les étapes de construction pour éviter les tâches redondantes. Docker peut ignorer les instructions inchangées dans votre Dockerfile en réutilisant la couche précédemment créée. Il base l’étape suivante sur cette couche existante, au lieu d’en créer une nouvelle.
Vous pouvez le voir en modifiant votre Dockerfile comme suit :
FROM ubuntu:latest
COPY foo.txt /foo.txt
RUN date +%Y-%m-%d > /built-on.txt
La troisième étape de construction a changé. Reconstruisez maintenant votre image :
$ docker build . -t demo:latest
Sending build context to Docker daemon 3.584kB
Step 1/3 : FROM ubuntu:latest
---> df5de72bdb3b
Step 2/3 : COPY foo.txt /foo.txt
---> Using cache
---> 4932aede6a15
Step 3/3 : RUN date +%Y-%m-%d > /built-on.txt
---> Running in 2b91ec0462c4
Removing intermediate container 2b91ec0462c4
---> c6647ff378c1
Successfully built c6647ff378c1
Successfully tagged demo:latest
La deuxième étape de construction montre comme Using cache
et produit le même ID de couche. Docker pourrait ignorer la construction de cette couche car elle a déjà été créée plus tôt et foo.txt
n’a pas changé depuis la première version.
Cette mise en cache ne fonctionne que jusqu’au moment où un calque est modifié. Toutes les étapes après cette couche devront également être reconstruites afin qu’elles soient basées sur la nouvelle révision du système de fichiers.
Couches et opérations d’extraction
Un autre avantage des calques est la façon dont ils permettent des extractions d’image partielles. Une fois que vous avez téléchargé quelques images sur votre machine, vous constaterez souvent que de nouveaux pulls peuvent ignorer certaines couches que vous avez déjà. Cette image contient 13 calques mais seuls six ont dû être téléchargés par l’opération d’extraction :
docker pull php:8.0-apache
8.0-apache: Pulling from library/php
7a6db449b51b: Already exists
ad2afdb99a9d: Already exists
dbc5aa907229: Already exists
82f252ab4ad1: Already exists
bf5b34fc9894: Already exists
6161651d3d95: Already exists
cf2adf296ef1: Already exists
f0d7c5221e44: Pull complete
f647198f6316: Pull complete
c37afe1da4e5: Pull complete
09c93531cbca: Pull complete
fef371007dd3: Pull complete
52043dbb1c06: Pull complete
Digest: sha256:429889e8f9eac0a806a005b0728a004303b0d49d77b09496d39158707abd6280
Status: Downloaded newer image for php:8.0-apache
docker.io/library/php:8.0-apache
Les autres couches étaient déjà présentes sur l’hôte Docker afin qu’elles puissent être réutilisées. Cela améliore les performances et évite de gaspiller la bande passante du réseau.
Inspection des calques d’image
Vous pouvez répertorier les couches d’une image en exécutant la commande docker image history
commande. Chaque couche affiche l’ID de l’image créée et l’instruction Dockerfile qui a provoqué la modification. Vous pouvez également voir la taille totale du contenu dans le calque.
$ docker image history
IMAGE CREATED CREATED BY SIZE COMMENT
6f653c6a60fa 4 minutes ago /bin/sh -c date > /built-on.txt 29B
f8420d1a96f3 4 minutes ago /bin/sh -c #(nop) COPY file:a5630a7506b26a37... 0B
df5de72bdb3b 4 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 4 weeks ago /bin/sh -c #(nop) ADD file:396eeb65c8d737180... 77.8MB
La dernière couche s’affiche comme <missing>
parce qu’il fait référence à une couche dans le ubuntu:latest
image de base. Ceci n’est pas disponible localement, car seule la couche finale de l’image de base (df5de72bdb3b
) est supprimé pendant les générations. Il n’est pas nécessaire de tirer indépendamment toutes les couches intermédiaires lorsque vous souhaitez utiliser une image spécifique.
Sommaire
Les images et les calques Docker sont généralement des termes interchangeables. Un calque est une image et une image est formée d’un ou plusieurs calques. La principale différence réside dans les balises : une image sera étiquetée et conçue pour les utilisateurs finaux, tandis que le terme « calque » fait normalement référence aux images intermédiaires non étiquetées créées dans le cadre d’une opération de construction. Ceux-ci ne sont pas visibles à moins que vous ne les cherchiez.
Il existe un autre sujet lié aux calques : l’exécution de conteneurs ajoute un calque inscriptible supplémentaire au-dessus de leur image. Les couches provenant de l’image du conteneur sont en lecture seule, de sorte que les modifications du système de fichiers effectuées par le conteneur ciblent sa couche inscriptible éphémère. La couche inscriptible est supprimée lorsque le conteneur est arrêté ou supprimé.