Docker à partir du sol comprendre les images

Les conteneurs Docker sont à la hausse en tant que pratique recommandée pour le déploiement et la gestion de systèmes répartis en nuage. Les conteneurs sont des instances d'images Docker. Il s'avère qu'il y a beaucoup de choses à savoir et à comprendre sur les images. 

Dans ce didacticiel en deux parties, je couvrirai les images de Docker en profondeur. Dans cette partie, je commencerai par les principes de base, puis je passerai à la conception et à l'inspection des éléments internes de l'image. Dans la deuxième partie, je traiterai de la création de vos propres images, du dépannage et de l'utilisation de référentiels d'images.. 

Lorsque vous vous présenterez de l'autre côté, vous aurez une solide compréhension de ce que sont exactement les images Docker et de la manière de les utiliser efficacement dans vos propres applications et systèmes..

Comprendre les couches

Docker gère les images à l'aide d'un pilote de stockage back-end. Il existe plusieurs pilotes pris en charge tels que AUFS, BTRFS et overlays. Les images sont constituées de couches ordonnées. Vous pouvez considérer une couche comme un ensemble de modifications du système de fichiers. Lorsque vous prenez toutes les couches et les empilez, vous obtenez une nouvelle image contenant toutes les modifications accumulées.. 

La partie commandée est importante. Si vous ajoutez un fichier dans un calque et le supprimez dans un autre, vous feriez mieux de le faire dans le bon ordre. Docker garde la trace de chaque couche. Une image peut être composée de dizaines de calques (la limite actuelle est de 127). Chaque couche est très légère. L'avantage des calques est que les images peuvent partager des calques. 

Si vous avez beaucoup d'images basées sur des couches similaires, telles que le système d'exploitation de base ou des packages communs, toutes ces couches communes seront stockées une seule fois et la surcharge par image correspondra uniquement aux couches uniques de cette image..

Copier en écriture

Lorsqu'un nouveau conteneur est créé à partir d'une image, toutes les couches d'image sont en lecture seule et une couche mince de lecture-écriture est ajoutée en haut. Toutes les modifications apportées au conteneur spécifique sont stockées dans cette couche. 

Cela ne signifie pas pour autant que le conteneur ne peut pas modifier les fichiers de sa couche d'image. Cela peut certainement. Mais il créera une copie dans sa couche supérieure et, à partir de ce moment, quiconque tentera d'accéder au fichier obtiendra la copie de la couche supérieure. Lorsque des fichiers ou des répertoires sont supprimés des couches inférieures, ils sont masqués. Les couches d'image d'origine sont identifiées par un hachage basé sur le contenu cryptographique. La couche lecture-écriture du conteneur est identifiée par un UUID.

Cela permet une stratégie de copie sur écriture pour les images et les conteneurs. Docker réutilise les mêmes éléments autant que possible. Docker crée une nouvelle copie uniquement lorsqu'un élément est modifié..

Considérations de conception pour les images Docker

L'organisation unique en couches et la stratégie de copie sur écriture promeuvent certaines des meilleures pratiques pour la création et la composition d'images Docker..

Minimal Images: Less Is More

Les images Docker procurent d’énormes avantages du point de vue de la stabilité, de la sécurité et du temps de chargement, plus elles sont petites. Vous pouvez créer de très petites images à des fins de production. Si vous avez besoin de dépanner, vous pouvez toujours installer des outils dans un conteneur. 

Si vous écrivez vos données, journaux et tout le reste uniquement dans des volumes montés, vous pouvez utiliser tout votre arsenal d'outils de débogage et de dépannage sur l'hôte. Nous verrons bientôt comment contrôler très soigneusement les fichiers de votre image Docker..

Combiner des couches

Les couches sont géniales, mais il y a une limite, et il y a une surcharge associée aux couches. Trop de couches peuvent endommager l'accès au système de fichiers à l'intérieur du conteneur (car chaque couche peut avoir ajouté ou supprimé un fichier ou un répertoire), et elles encombrent simplement votre propre système de fichiers..

Par exemple, si vous installez plusieurs paquets, vous pouvez avoir une couche pour chaque paquet en installant chaque paquet dans une commande RUN distincte dans votre fichier Docker:

Exécuter apt-get update Exécuter apt-get -y install package_1 Exécuter apt-get -y install package_2 Exécuter apt-get -y install package_3

Ou vous pouvez les combiner en une couche avec une seule commande RUN.

Lancez apt-get update && \ apt-get -y install package_1 && \ apt-get -y install package_2 && \ apt-get -y install package_3 

Choisir une image de base

Votre image de base (pratiquement personne ne construit des images à partir de zéro) est souvent une décision majeure. Il peut contenir de nombreuses couches et ajouter de nombreuses fonctionnalités, mais également beaucoup de poids. La qualité de l'image et de l'auteur est également critique. Vous ne voulez pas baser vos images sur une image floconneuse où vous n'êtes pas sûr de ce qu'il y a dedans et si vous pouvez faire confiance à l'auteur.

Il existe des images officielles pour de nombreuses distributions, langages de programmation, bases de données et environnements d'exécution. Parfois, les options sont écrasantes. Prenez votre temps et faites un choix judicieux.

Inspection des images

Regardons quelques images. Voici une liste des images actuellement disponibles sur ma machine:

REPOSITORY TAG IMAGE ID TAILLE CREE python Dernier 775dae9b960e Il ya 12 jours 687 MB d4w / nsenter Dernier 9e4f13a0901e Il y a 4 mois 83.8 kB ustensile de sécurité avec du ssh mois plus tôt 1.85 kB alpin 4e38e38c8ce0 il y a 7 mois 4,8 Mo nsqio / nsq 2a82c70fe5e3 2 mois auparavant 70.7 Mo

Le référentiel et la balise identifient l'image pour l'homme. Si vous essayez simplement d'exécuter ou d'extraire en utilisant un nom de référentiel sans spécifier la balise, la balise "latest" est utilisée par défaut. L'identifiant de l'image est un identifiant unique.

Ouvrons et inspectons l'image du monde bonjour:

> docker inspecte hello-world ["Id": sha256: c54a2cc56cbb2f ... e7e2720f70976c4b75237dc "," RepoTags ": [hello-world: dernier"] ], "Parent": "", "Commentaire": "", "Créé": "2016-07-01T19: 39: 27: 32.532838486Z", "Conteneur": "562cadb4d17bbf30b58a… bf637f1d2d7f8afbef666", "ContainerConfig": "Nom de l'hôte ":" c65bc554a4b7 "," Nom du domaine ":" "," Utilisateur ":" "," AttachStdin ": false," AttachStdout ": false," AttachStderr ": false," Tty ": false," OpenStdin ": false, "StdinOnce": false, "Env": ["PATH = / usr / bin: / usr / sbin: / usr / bin: / sbin: / bin"], "Cmd": ["/ bin / sh", " -c "," # (nop) CMD [\ "/ hello \"] "," Image ":" sha256: 0f9bb7da10de694… 5ab0fe537ce1cd831e "," Volumes ": null," WorkingDir ":" ",", "Entrypoint": null, "OnBuild": null, "Labels": , "DockerVersion": "1.10.3", "Author": "", "Config": "Hostname": "c65bc554a4b7", "Nom de domaine": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "Ouvrir. Stdin ": false," StdinOnce ": false," Env ": [" CHEMIN = / usr / sbin: / usr / bin: / sbin: / bin "]," Cmd ": [" / bonjour "]," Image ":" sha256: 0f9bb7da10de694b… b0fe537ce1cd831e "," Volumes ": null," WorkingDir ":" "," Entrypoint ": null," OnBuild ": null," Libellés ": ," Architecture ": ," Architecture ":" amd64 " , "Os": "linux", "Taille": 1848, "VirtualSize": 1848, "GraphDriver": "Nom": "aufs", "Données": null, "RootFS": "Type": "layers", "Layers": ["sha256: a02596fdd012f22b03a… 079c3e8cebceb4262d7"]]

Il est intéressant de voir combien d’informations sont associées à chaque image. Je ne vais pas passer en revue chaque article. Je mentionnerai simplement un élément intéressant que les entrées "container" et "containerConfig" sont destinées à un conteneur temporaire créé par Docker lorsqu’il construit l’image. Ici, je veux me concentrer sur la dernière section de "RootFS". Vous pouvez obtenir uniquement cette partie en utilisant le support de modélisation Go de la commande inspect:

> docker inspecter -f '.RootFS' hello-world layers [sha256: a02596fdd012f22b03af6a… 8357b079c3e8cebceb4262d7]

Cela fonctionne, mais nous avons perdu la belle mise en forme. Je préfère utiliser jq:

> docker inspecte bonjour le monde | jq. [0] .RootFS "Type": "couches", "Couches": ["sha256: a02596fdd012f22b03af6a… 7507558357b079c3e8cebceb4262d7"] 

Vous pouvez voir que le type est "Layers", et qu'il n'y a qu'un seul calque. 

Inspectons les couches de l'image Python:

> docker inspect python | jq. b. 52932c7d4924c9bfa6c9 "," sha256: 311f330fa783aef35 ... e8283e06cf1919a47002d "," sha256: L'emballage de la réserve

Sensationnel. Sept couches. Mais quelles sont ces couches? Nous pouvons utiliser la commande history pour comprendre cela:

IMAGE CRÉÉE PAR TAILLE 775dae9b960e / bin / sh -c # (nop) CMD ["python3"] 0 B  Il y a 12 jours / bin / sh -c cd / usr / local / bin && … 48 B  Il y a 12 jours / bin / sh -c set -ex && buildDeps = '… 66.9 MB  Il y a 12 jours / bin / sh -c # (nop) ENV PYTHON_PIP_V… 0 B  Il y a 12 jours / bin / sh -c # (nop) ENV PYTHON_VERSI… 0 B  Il y a 12 jours / bin / sh -c # (nop) ENV GPG_KEY = 0D96… 0 B  Il y a 12 jours / bin / sh -c apt-get update && apt-ge… 7.75 MB  Il y a 12 jours / bin / sh -c # (nop) ENV LANG = C.UTF-8 0 B  Il y a 12 jours / bin / sh -c # (nop) ENV PATH = / usr / lo… 0 B  Il y a 13 jours / bin / sh -c apt-get update && apt-ge… 323 MB  Il y a 13 jours / bin / sh -c apt-get update && apt-ge… 123 MB  Il y a 13 jours / bin / sh -c apt-get update && apt-ge… 44.3 MB  Il y a 13 jours / bin / sh -c # (nop) CMD ["/ bin / bash"… 0 B  Il y a 13 jours / bin / sh -c # (nop) Fichier ADD: 89ecb642… 123 MB

D'ACCORD. Ne vous inquiétez pas. Il ne manque rien Ceci est juste une interface utilisateur terrible. Auparavant, les couches avaient un identifiant d'image avant Docker 1.10, mais plus maintenant. L'ID de la couche supérieure n'est pas vraiment l'ID de cette couche. C'est l'ID de l'image Python. "CREATED BY" est tronqué, mais vous pouvez voir la commande complète si vous passez --pas de tronc. Je vous épargne la sortie ici en raison de limitations de largeur de page qui nécessiteront un retour à la ligne extrême.

Comment obtenez-vous des images? Il y a trois façons:

  • Tirer / courir
  • Charge
  • Construire

Lorsque vous exécutez un conteneur, vous spécifiez son image. Si l'image n'existe pas sur votre système, elle est extraite d'un registre Docker (par défaut, DockerHub). Alternativement, vous pouvez tirer directement sans exécuter le conteneur.

Vous pouvez également charger une image que quelqu'un vous a envoyée sous forme de fichier tar. Docker le supporte nativement.

Enfin, et le plus intéressant, vous pouvez construire vos propres images, qui sont le sujet de la deuxième partie.

Conclusion

Les images Docker sont basées sur un système de fichiers en couches qui offre de nombreux avantages pour les cas d'utilisation pour lesquels les conteneurs sont conçus, tels que la légèreté et le partage de pièces communes, de sorte que de nombreux conteneurs puissent être déployés et exécutés sur le même ordinateur de manière économique.. 

.