Ils ont le plus de sens pour moi avec un exemple ...
Examen des couches de votre propre construction avec Docker Diff
Prenons un exemple artificiel de Dockerfile:
FROM busybox
RUN mkdir /data
# imagine this is downloading source code
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one
RUN chmod -R 0777 /data
# imagine this is compiling the app
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/two
RUN chmod -R 0777 /data
# and now this cleans up that downloaded source code
RUN rm /data/one
CMD ls -alh /data
Chacune de ces dd
commandes génère un fichier de 1 Mo sur le disque. Permet de construire l'image avec un indicateur supplémentaire pour enregistrer les conteneurs temporaires:
docker image build --rm=false .
Dans la sortie, vous verrez chacune des commandes en cours d'exécution se produire dans un conteneur temporaire que nous conservons maintenant au lieu de supprimer automatiquement:
...
Step 2/7 : RUN mkdir /data
---> Running in 04c5fa1360b0
---> 9b4368667b8c
Step 3/7 : RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one
---> Running in f1b72db3bfaa
1024+0 records in
1024+0 records out
1048576 bytes (1.0MB) copied, 0.006002 seconds, 166.6MB/s
---> ea2506fc6e11
Si vous exécutez un docker diff
sur chacun de ces ID de conteneur, vous verrez quels fichiers ont été créés dans ces conteneurs:
$ docker diff 04c5fa1360b0 # mkdir /data
A /data
$ docker diff f1b72db3bfaa # dd if=/dev/zero bs=1024 count=1024 of=/data/one
C /data
A /data/one
$ docker diff 81c607555a7d # chmod -R 0777 /data
C /data
C /data/one
$ docker diff 1bd249e1a47b # dd if=/dev/zero bs=1024 count=1024 of=/data/two
C /data
A /data/two
$ docker diff 038bd2bc5aea # chmod -R 0777 /data
C /data/one
C /data/two
$ docker diff 504c6e9b6637 # rm /data/one
C /data
D /data/one
Chaque ligne précédée d'un signe A
ajoute le fichier, C
indique une modification apportée à un fichier existant et D
indique une suppression.
Voici la partie TL; DR
Chacun de ces systèmes de fichiers de conteneur diffs ci-dessus va dans une "couche" qui est assemblée lorsque vous exécutez l'image en tant que conteneur. Le fichier entier se trouve dans chaque couche lorsqu'il y a un ajout ou une modification, de sorte que chacune de ces chmod
commandes, malgré le simple changement d'un bit d'autorisation, entraîne la copie du fichier entier dans la couche suivante. Le fichier supprimé / data / one est toujours dans les couches précédentes, 3 fois en fait, et sera copié sur le réseau et stocké sur le disque lorsque vous tirez l'image.
Examen des images existantes
Vous pouvez voir les commandes qui entrent dans la création des couches d'une image existante avec la docker history
commande. Vous pouvez également exécuter un docker image inspect
sur une image et voir la liste des couches sous la section RootFS.
Voici l'historique de l'image ci-dessus:
IMAGE CREATED CREATED BY SIZE COMMENT
a81cfb93008c 4 seconds ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "ls -… 0B
f36265598aef 5 seconds ago /bin/sh -c rm /data/one 0B
c79aff033b1c 7 seconds ago /bin/sh -c chmod -R 0777 /data 2.1MB
b821dfe9ea38 10 seconds ago /bin/sh -c dd if=/dev/zero bs=1024 count=102… 1.05MB
a5602b8e8c69 13 seconds ago /bin/sh -c chmod -R 0777 /data 1.05MB
08ec3c707b11 15 seconds ago /bin/sh -c dd if=/dev/zero bs=1024 count=102… 1.05MB
ed27832cb6c7 18 seconds ago /bin/sh -c mkdir /data 0B
22c2dd5ee85d 2 weeks ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ADD file:2a4c44bdcb743a52f… 1.16MB
Les couches les plus récentes sont répertoriées en haut. À noter, il y a deux couches en bas qui sont assez anciennes. Ils proviennent de l'image busybox elle-même. Lorsque vous créez une image, vous héritez de tous les calques de l'image que vous spécifiez dans la FROM
ligne. Des couches sont également ajoutées pour modifier les métadonnées de l'image, comme la CMD
ligne. Ils prennent à peine de la place et servent davantage à enregistrer les paramètres qui s'appliquent à l'image que vous exécutez.
Pourquoi des couches?
Les couches ont quelques avantages. Premièrement, ils sont immuables. Une fois créé, ce calque identifié par un hachage sha256 ne changera jamais. Cette immuabilité permet aux images de se construire en toute sécurité et de se séparer les unes des autres. Si deux fichiers docker ont le même ensemble initial de lignes et sont construits sur le même serveur, ils partageront le même ensemble de couches initiales, économisant de l'espace disque. Cela signifie également que si vous reconstruisez une image, avec seulement les dernières lignes du Dockerfile subissant des modifications, seules ces couches doivent être reconstruites et le reste peut être réutilisé à partir du cache de couches. Cela peut accélérer la reconstruction des images du docker.
À l'intérieur d'un conteneur, vous voyez le système de fichiers image, mais ce système de fichiers n'est pas copié. En plus de ces couches d'image, le conteneur monte sa propre couche de système de fichiers en lecture-écriture. Chaque lecture d'un fichier passe par les couches jusqu'à ce qu'elle atteigne une couche qui a marqué le fichier pour suppression, a une copie du fichier dans cette couche, ou la lecture manque de couches à rechercher. Chaque écriture apporte une modification dans la couche lecture-écriture spécifique au conteneur.
Réduire le gonflement de la couche
L'un des inconvénients des couches est la création d'images qui dupliquent des fichiers ou expédient des fichiers supprimés dans une couche ultérieure. La solution consiste souvent à fusionner plusieurs commandes en une seule RUN
commande. En particulier, lorsque vous modifiez des fichiers existants ou supprimez des fichiers, vous souhaitez que ces étapes s'exécutent dans la même commande où elles ont été créées pour la première fois. Une réécriture du Dockerfile ci-dessus ressemblerait à ceci:
FROM busybox
RUN mkdir /data \
&& dd if=/dev/zero bs=1024 count=1024 of=/data/one \
&& chmod -R 0777 /data \
&& dd if=/dev/zero bs=1024 count=1024 of=/data/two \
&& chmod -R 0777 /data \
&& rm /data/one
CMD ls -alh /data
Et si vous comparez les images résultantes:
- busybox: ~ 1 Mo
- première image: ~ 6 Mo
- deuxième image: ~ 2 Mo
Simplement en fusionnant quelques lignes dans l'exemple artificiel, nous avons obtenu le même contenu résultant dans notre image et avons réduit notre image de 5 Mo au fichier de 1 Mo que vous voyez dans l'image finale.