Comprendre les couches de l'image
Explication
Comme vous l'avez appris dans Qu'est-ce qu'une image ?, les images de conteneur sont composées de couches. Et chacune de ces couches, une fois créée, est immuable. Mais, qu'est-ce que cela signifie réellement ? Et comment ces couches sont-elles utilisées pour créer le système de fichiers qu'un conteneur peut utiliser ?
Couches d'image
Chaque couche d'une image contient un ensemble de modifications du système de fichiers - ajouts, suppressions ou modifications. Examinons une image théorique :
- La première couche ajoute des commandes de base et un gestionnaire de paquets, comme apt.
- La deuxième couche installe un runtime Python et pip pour la gestion des dépendances.
- La troisième couche copie un fichier requirements.txt spécifique à une application.
- La quatrième couche installe les dépendances spécifiques à cette application.
- La cinquième couche copie le code source réel de l'application.
Cet exemple pourrait ressembler à ceci :


Ceci est bénéfique car cela permet de réutiliser les couches entre les images. Par exemple, imaginez que vous vouliez créer une autre application Python. Grâce à la superposition, vous pouvez exploiter la même base Python. Cela rendra les constructions plus rapides et réduira la quantité de stockage et de bande passante requise pour distribuer les images. La superposition d'images pourrait ressembler à ce qui suit :


Les couches vous permettent d'étendre les images des autres en réutilisant leurs couches de base, vous permettant d'ajouter uniquement les données dont votre application a besoin.
Empiler les couches
La superposition est rendue possible par le stockage adressable par contenu et les systèmes de fichiers d'union. Bien que cela devienne technique, voici comment cela fonctionne :
- Une fois chaque couche téléchargée, elle est extraite dans son propre répertoire sur le système de fichiers de l'hôte.
- Lorsque vous exécutez un conteneur à partir d'une image, un système de fichiers d'union est créé où les couches sont empilées les unes sur les autres, créant une nouvelle vue unifiée.
- Lorsque le conteneur démarre, son répertoire racine est défini sur l'emplacement de ce répertoire unifié, à l'aide de
chroot
.
Lorsque le système de fichiers d'union est créé, en plus des couches d'image, un répertoire est créé spécifiquement pour le conteneur en cours d'exécution. Cela permet au conteneur d'apporter des modifications au système de fichiers tout en laissant les couches d'image d'origine intactes. Cela vous permet d'exécuter plusieurs conteneurs à partir de la même image sous-jacente.
Essayez-le
Dans ce guide pratique, vous allez créer de nouvelles couches d'image manuellement à l'aide de la commande docker container commit
. Notez que vous créerez rarement des images de cette manière, car vous utiliserez normalement un Dockerfile. Mais, cela facilite la compréhension de son fonctionnement.
Créer une image de base
Dans cette première étape, vous allez créer votre propre image de base que vous utiliserez ensuite pour les étapes suivantes.
-
Téléchargez et installez Docker Desktop.
-
Dans un terminal, exécutez la commande suivante pour démarrer un nouveau conteneur :
$ docker run --name=base-container -ti ubuntu
Une fois l'image téléchargée et le conteneur démarré, vous devriez voir une nouvelle invite de shell. Elle s'exécute à l'intérieur de votre conteneur. Elle ressemblera à ce qui suit (l'ID du conteneur variera) :
root@d8c5ca119fcd:/#
-
À l'intérieur du conteneur, exécutez la commande suivante pour installer Node.js :
$ apt update && apt install -y nodejs
Lorsque cette commande s'exécute, elle télécharge et installe Node à l'intérieur du conteneur. Dans le contexte du système de fichiers d'union, ces modifications du système de fichiers se produisent dans le répertoire unique à ce conteneur.
-
Validez si Node est installé en exécutant la commande suivante :
$ node -e 'console.log("Hello world!")'
Vous devriez alors voir un « Hello world! » apparaître dans la console.
-
Maintenant que vous avez installé Node, vous êtes prêt à enregistrer les modifications que vous avez apportées en tant que nouvelle couche d'image, à partir de laquelle vous pouvez démarrer de nouveaux conteneurs ou créer de nouvelles images. Pour ce faire, vous utiliserez la commande
docker container commit
. Exécutez la commande suivante dans un nouveau terminal :$ docker container commit -m "Add node" base-container node-base
-
Affichez les couches de votre image à l'aide de la commande
docker image history
:$ docker image history node-base
Vous verrez une sortie similaire à la suivante :
IMAGE CREATED CREATED BY SIZE COMMENT d5c1fca2cdc4 10 seconds ago /bin/bash 126MB Add node 2b7cc08dcdbb 5 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 5 weeks ago /bin/sh -c #(nop) ADD file:07cdbabf782942af0… 69.2MB <missing> 5 weeks ago /bin/sh -c #(nop) LABEL org.opencontainers.… 0B <missing> 5 weeks ago /bin/sh -c #(nop) LABEL org.opencontainers.… 0B <missing> 5 weeks ago /bin/sh -c #(nop) ARG LAUNCHPAD_BUILD_ARCH 0B <missing> 5 weeks ago /bin/sh -c #(nop) ARG RELEASE 0B
Notez le commentaire « Add node » sur la première ligne. Cette couche contient l'installation de Node.js que vous venez de faire.
-
Pour prouver que votre image a Node installé, vous pouvez démarrer un nouveau conteneur en utilisant cette nouvelle image :
$ docker run node-base node -e "console.log('Hello again')"
Avec cela, vous devriez obtenir une sortie « Hello again » dans le terminal, montrant que Node a été installé et fonctionne.
-
Maintenant que vous avez terminé de créer votre image de base, vous pouvez supprimer ce conteneur :
$ docker rm -f base-container
Définition de l'image de base
Une image de base est une base pour la construction d'autres images. Il est possible d'utiliser n'importe quelle image comme image de base. Cependant, certaines images sont intentionnellement créées comme des blocs de construction, fournissant une base ou un point de départ pour une application.
Dans cet exemple, vous ne déploierez probablement pas cette image
node-base
, car elle ne fait encore rien. Mais c'est une base que vous pouvez utiliser pour d'autres constructions.
Construire une image d'application
Maintenant que vous avez une image de base, vous pouvez étendre cette image pour créer des images supplémentaires.
-
Démarrez un nouveau conteneur en utilisant l'image node-base nouvellement créée :
$ docker run --name=app-container -ti node-base
-
À l'intérieur de ce conteneur, exécutez la commande suivante pour créer un programme Node :
$ echo 'console.log("Hello from an app")' > app.js
Pour exécuter ce programme Node, vous pouvez utiliser la commande suivante et voir le message imprimé à l'écran :
$ node app.js
-
Dans un autre terminal, exécutez la commande suivante pour enregistrer les modifications de ce conteneur en tant que nouvelle image :
$ docker container commit -c "CMD node app.js" -m "Add app" app-container sample-app
Cette commande crée non seulement une nouvelle image nommée
sample-app
, mais ajoute également une configuration supplémentaire à l'image pour définir la commande par défaut lors du démarrage d'un conteneur. Dans ce cas, vous la définissez pour exécuter automatiquementnode app.js
. -
Dans un terminal en dehors du conteneur, exécutez la commande suivante pour afficher les couches mises à jour :
$ docker image history sample-app
Vous verrez alors une sortie qui ressemble à ce qui suit. Notez que le commentaire de la couche supérieure a « Add app » et que la couche suivante a « Add node » :
IMAGE CREATED CREATED BY SIZE COMMENT c1502e2ec875 About a minute ago /bin/bash 33B Add app 5310da79c50a 4 minutes ago /bin/bash 126MB Add node 2b7cc08dcdbb 5 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 5 weeks ago /bin/sh -c #(nop) ADD file:07cdbabf782942af0… 69.2MB <missing> 5 weeks ago /bin/sh -c #(nop) LABEL org.opencontainers.… 0B <missing> 5 weeks ago /bin/sh -c #(nop) LABEL org.opencontainers.… 0B <missing> 5 weeks ago /bin/sh -c #(nop) ARG LAUNCHPAD_BUILD_ARCH 0B <missing> 5 weeks ago /bin/sh -c #(nop) ARG RELEASE 0B
-
Enfin, démarrez un nouveau conteneur en utilisant la toute nouvelle image. Puisque vous avez spécifié la commande par défaut, vous pouvez utiliser la commande suivante :
$ docker run sample-app
Vous devriez voir votre message d'accueil apparaître dans le terminal, provenant de votre programme Node.
-
Maintenant que vous avez terminé avec vos conteneurs, vous pouvez les supprimer en utilisant la commande suivante :
$ docker rm -f app-container
Ressources supplémentaires
Si vous souhaitez approfondir les sujets que vous avez appris, consultez les ressources suivantes :
Prochaines étapes
Comme nous l'avons laissé entendre plus tôt, la plupart des constructions d'images n'utilisent pas docker container commit
. Au lieu de cela, vous utiliserez un Dockerfile qui automatise ces étapes pour vous.