Comprendre les Layers dans les images Docker
Chaque fois que Docker exécute une instruction dans un Dockerfile, il crée une nouvelle couche (layer) qui contient les modifications apportées par cette instruction. Ces couches sont empilées de manière séquentielle et peuvent être réutilisées si une couche n’a pas changé entre deux constructions d'images. Cela permet à Docker de gagner en efficacité lors des constructions d'images successives en réutilisant des couches qui n’ont pas été modifiées, plutôt que de tout reconstruire à chaque fois.
Comment les layers fonctionnent ils ?
Quand vous écrivez un Dockerfile, chaque instruction (comme RUN, COPY, ADD, etc.) crée une nouvelle couche.
Par exemple, si vous avez :
FROM ubuntu
RUN apt update
RUN apt install -y curl
Cela générera trois couches :
- La première couche est celle qui provient de l'image de base ubuntu.
- La deuxième couche contient les résultats de la commande apt update.
- La troisième couche contient les résultats de la commande apt install -y curl.
Une fois qu'une couche est créée, elle ne peut plus être modifiée. Si une nouvelle instruction modifie quelque chose (par exemple, un fichier ou un répertoire), Docker crée une nouvelle couche qui contient cette modification.
Les couches sont empilées dans l'ordre dans lequel elles ont été créées. La première couche est la base (par exemple, FROM ubuntu), et chaque couche suivante est une modification qui s'ajoute à l'image.
Docker utilise un mécanisme de cache pour éviter de recréer une couche si son contenu n’a pas changé depuis la dernière fois. Cela permet de gagner du temps lors de la construction des images. Par exemple, si vous avez une instruction RUN qui installe un package, mais que le contenu de la couche n'a pas changé (par exemple, les mêmes fichiers sont copiés ou la même commande est exécutée), Docker utilisera le cache pour ne pas refaire cette étape.
Cela améliore l'efficacité de la construction des images. Par contre, si un fichier ou une instruction change, Docker va reconstruire cette couche et toutes les couches suivantes.
Construction d'image et des layers
Prenons un Dockerfile simple :
FROM ubuntu:22.04
RUN apt update
RUN apt install -y curl
COPY ./myapp /app
- Layer 1 : Docker télécharge l'image de base ubuntu:22.04 (si elle n'est pas déjà en cache).
- Layer 2 : Docker exécute RUN apt update pour mettre à jour les index des paquets. Cette couche contient l'état du système après la mise à jour.
- Layer 3 : Docker exécute RUN apt install -y curl, qui installe curl. Cette couche contient les modifications apportées par l'installation de curl.
- Layer 4 : Docker exécute COPY ./myapp /app, qui copie le répertoire ./myapp depuis l'hôte vers le conteneur à l'emplacement /app. Cette couche contient les fichiers copiés dans le conteneur.
Ces couches sont empilées et, une fois l'image construite, vous aurez une image qui contient toutes ces couches dans cet ordre. L'image finale n’est qu'une superposition de ces couches, et quand Docker exécute un conteneur à partir de l'image, il lit et combine ces couches pour créer un système de fichiers cohérent.
Les avantages des layers
Docker peut réutiliser les couches existantes lors de la création de nouvelles images. Si une couche n’a pas changé, Docker réutilisera cette couche depuis son cache sans avoir à la reconstruire. Cela réduit le temps de construction des images.
Docker utilise un système de fichier en copie sur écriture (Copy-on-write, ou COW). Cela signifie que chaque conteneur qui utilise une image va partager les mêmes couches de l'image. Si plusieurs conteneurs sont créés à partir de la même image, ils partagent les mêmes couches, économisant ainsi de l'espace disque.
Chaque couche est une modification indépendante de l'image, ce qui facilite la mise à jour ou le remplacement de certaines parties de l'image sans avoir à reconstruire l'image entière. Par exemple, vous pouvez juste remplacer une couche qui installe un package sans avoir à refaire toute l'image.
Les inconvénients des layers
Trop de couches peuvent entraîner des images plus volumineuse. Par exemple, si vous avez une instruction RUN pour chaque modification minime, chaque commande crée une nouvelle couche, ce qui peut augmenter la taille de l'image et rendre le processus de construction moins efficace.
Si vous avez une instruction qui change fréquemment (par exemple, télécharger un fichier à chaque construction), Docker invalidera le cache de cette couche et de toutes les couches suivantes, ce qui peut entraîner une reconstruction plus lente.
Bonnes pratiques pour gérer les layers
Il est souvent recommandé de combiner plusieurs instructions RUN en une seule pour réduire le nombre de couches.
RUN apt update && apt install -y curl && apt install -y vim
Cela crée une seule couche au lieu de trois.
Comme avec les fichiers COPY ou ADD, il est important d'ignorer les fichiers inutiles en utilisant un fichier .dockerignore. Cela permet d'éviter de copier des fichiers dans l'image qui ne sont pas nécessaires et d'éviter ainsi d’ajouter des couches inutiles.
Si vous avez une instruction RUN qui dépend d'une source qui change fréquemment (comme la copie d'un fichier, ou l'installation d'un package), placez les instructions qui changent moins souvent en premier dans le Dockerfile. Cela permet à Docker de réutiliser les couches précédentes et d'optimiser le processus de construction.
Conclusion
Les layers dans Docker sont essentiels pour la performance, l'efficacité et la modularité des images. Grâce à la réutilisation des couches, Docker peut construire et distribuer des images de manière rapide et optimisée. Comprendre et gérer correctement les couches peut réduire le temps de construction, la taille des images et améliorer la maintenance des Dockerfiles.
ressources supplémentaires
Documentation layers images docker: ici