Comment utiliser plusieurs contextes de construction Docker pour rationaliser l’assemblage d’images
Le concept de Docker de « contexte de construction » est l’une de ses caractéristiques les plus restrictives et les plus mal comprises. Le contexte de construction définit les fichiers et dossiers locaux que vous pouvez référencer dans votre Dockerfile. Le contenu en dehors de celui-ci ne peut pas être utilisé, ce qui entrave souvent les procédures de construction complexes.
BuildKit v0.8 améliore cette situation en vous permettant d’utiliser plusieurs contextes avec chaque build que vous effectuez. Cela facilite le référencement de fichiers qui peuvent résider dans des emplacements complètement séparés, comme un fichier dans votre répertoire de travail et une dépendance à une URL distante.
Dans cet article, nous expliquerons pourquoi plusieurs contextes de génération sont utiles et comment vous pouvez les utiliser avec la dernière version de Docker CLI. Récapitulons d’abord ce qu’est le contexte de construction et pourquoi tant de personnes ont rencontré des problèmes dans le passé.
Sommaire
Objectif du contexte de génération
Docker est basé sur un démon. Le processus qui exécute vos versions d’image est indépendant du processus CLI qui émet la commande. Le démon peut être situé sur un hôte distant qui ne peut pas accéder directement au système de fichiers de votre machine.
Le contexte de génération fait référence aux fichiers qui sont transférés au démon Docker lorsqu’une génération se produit. C’est pourquoi seul le contenu du contexte peut être référencé par votre Dockerfile.
Il est courant de courir docker build
avec .
comme argument, ce qui fait de votre répertoire de travail le contexte de construction :
docker build -t my-website:latest .
Cela permet des références à n’importe quel chemin à l’intérieur de votre répertoire de travail :
FROM httpd:latest COPY index.html /var/www/html/index.html
Vous ne pouvez pas tendre la main pour copier quoi que ce soit au dessus le répertoire de travail dans votre système de fichiers :
FROM httpd:latest COPY index.html /var/www/html/index.html COPY ../company-css/company.css /var/www/html/company.css
Chaque fichier dont vous avez besoin dans votre image de conteneur doit exister dans un répertoire unique que vous pouvez utiliser comme contexte de génération. Cela peut être problématique dans des situations comme celle illustrée ci-dessus, où vous souhaitez extraire des dépendances à partir de sources qui ne figurent pas dans l’arborescence de votre projet.
Utilisation de plusieurs contextes de génération
Plusieurs contextes de construction sont désormais pris en charge dans BuildKit v0.8 et versions ultérieures lorsque vous optez pour la syntaxe Dockerfile v1.4. Ces versions sont livrées avec la CLI Docker à partir de la version 20.10.13. Vous devriez pouvoir les utiliser aujourd’hui si vous utilisez la dernière version de Docker.
Vous devez créer votre image avec BuildKit pour utiliser plusieurs contextes. Ils ne sont pas pris en charge par l’ancien constructeur. Utilisez le docker buildx build
commande au lieu de simple docker build
:
$ docker buildx build -t my-website:latest .
Vous pouvez maintenant utiliser le --build-context
flag pour définir plusieurs contextes de construction nommés :
$ docker buildx build -t my-website:latest . --build-context company-css=../company-css --build-context company-js=../company-js
Ajustez votre Dockerfile pour référencer le contenu de ces contextes :
#syntax=docker/dockerfile:1.4 FROM httpd:latest COPY index.html /var/www/html/index.html COPY --from=company-css /company.css /var/www/html/company.css COPY --from=company-js /company.js /var/www/html/company.js
Cela illustre comment vous pouvez copier des fichiers et des dossiers qui se trouvent en dehors de votre contexte de construction principal, quelle que soit leur position dans l’arborescence de votre système de fichiers.
La déclaration de syntaxe Dockerfile v1.4 est requise pour activer la prise en charge de la fonctionnalité. Vous pouvez ensuite utiliser le --from
options avec ADD
et COPY
instructions pour extraire des fichiers à partir de contextes de construction nommés, de la même manière que pour référencer une ressource dans une étape de construction antérieure.
Commande prioritaire
Plusieurs contextes de construction modifient l’ordre de résolution des ressources pour le --from
drapeau. Docker correspondra maintenant à la clé que vous fournissez (--from=key
) en suivant la procédure suivante :
- Recherchez un ensemble de contextes de génération nommé avec le
--build-context
drapeau. - Recherchez une étape de construction antérieure créée avec
FROM my-image:latest AS stage-name
. - Créez une nouvelle étape de construction en ligne en utilisant la clé donnée comme image de l’étape.
Cela signifie que vous pouvez utiliser des contextes nommés pour remplacer les dépendances distantes définies à l’aide des étapes de génération.
Considérez cet exemple :
#syntax=docker/dockerfile:1.4 FROM my-org/company-scss:latest AS css RUN sass company.scss company.css FROM httpd:latest COPY index.html /var/www/html/index.html COPY --from=css /company.css /var/www/html/company.css
Cette image Docker extrait certaines ressources distantes d’une autre image Docker partagée. Cela peut créer des difficultés lorsque vous testez votre projet – il peut y avoir un bogue dans la dépendance que vous souhaitez corriger rapidement.
Les contextes de génération nommés vous permettent de remplacer css
nom de scène pour fournir un fichier local à la place :
$ docker buildx build -t my-website:latest . --build-context css=css/
Cela copiera votre répertoire de travail css/company.css
fichier dans l’image finale, au lieu de la version fournie par le my-org/company-scss:latest
dépendance.
L’ordre de résolution signifie que des remplacements peuvent être appliqués même si votre image n’utilise pas d’étapes de construction nommées. En définissant un contexte de construction avec le même nom qu’une image, votre Dockerfile extraira le contenu de ce contexte, au lieu de l’image de registre d’origine.
$ docker buildx build -t my-website:latest . --build-context my-org/company-scss:latest=css/
URL distantes
Les contextes de construction nommés prennent en charge toutes les sources qui docker build
déjà accepté :
--build-context my-context=../local/path
– Un chemin dans votre système de fichiers.--build-context my-context=https://github.com/user/repo.git
– Un référentiel Git distant.--build-context my-context=https://example.com/data.tar
– Une archive distante fournie par un serveur HTTP.--build-context my-context=docker-image://busybox:latest
– Le contenu d’une autre image Docker.
Les sources distantes simplifient davantage les remplacements de dépendance. Vous pouvez pointer directement vers un référentiel Git forké ou vers une autre balise d’image Docker, tout en laissant votre Dockerfile inchangé.
Montage de fichiers à partir d’un contexte de génération
Les contextes de construction nommés fonctionnent avec RUN
consignes aussi. Vous pouvez utiliser --mount=from
pour exécuter un exécutable à partir d’un autre contexte de construction.
#syntax=docker/dockerfile:1.4 RUN --mount=from=name-of-build-context demo-executable
Cela monte le fichier sans le copier dans la couche actuelle, ce qui contribue à améliorer les performances. demo-executable
n’existera pas dans l’image finale.
Reconstruction précise des images
Un autre cas d’utilisation des contextes de construction nommés concerne la reconstruction d’images à l’avenir. Dockerfiles avec des instructions comme FROM alpine:3.15
ne sont pas totalement reproductibles. Les balises d’image sont mutable donc alpine:3.15
peut contenir un contenu différent à l’avenir, après la publication d’un nouveau correctif. Cela signifie que les images reconstruites ne sont pas garanties de produire les mêmes calques que leurs versions d’origine.
Vous pouvez résoudre ce problème en inspectant les métadonnées de la première compilation pour découvrir l’image de base exacte qui a été utilisée :
$ docker buildx imagetools inspect --format '{{json .BuildInfo}}' my-image:latest { ... "sources": [ { "type": "docker-image", "ref": "docker.io/library/alpine:3.15", "pin": "sha256:4edbd2beb5f78b1014028f4fbb99f3237d9561100b6881aabbf5acce2c4f9454" } ] ... }
Vous pouvez maintenant définir un contexte de construction nommé appelé alpine:3.15
qui pointe vers la version exacte qui a été précédemment utilisée :
$ docker buildx build -t my-image:latest . --build-context alpine:3.15=docker-image://alpine3.15@4edbd2beb5f78b1014028f4fbb99f3237d9561100b6881aabbf5acce2c4f9454
Cela simplifie la création d’une reconstruction précise d’une image précédemment créée, sans avoir à modifier son Dockerfile.
Conclusion
Plusieurs contextes de construction vous offrent plus d’options pour organiser des Dockerfiles complexes et des arborescences de répertoires de projets. Ils résolvent les problèmes d’utilisabilité de longue date que vous pouvez rencontrer avec un contexte de construction unique.
Les contextes de construction nommés vous permettent d’inclure des dépendances hors de l’arborescence et d’effectuer des remplacements ad hoc. Ils fonctionnent bien avec les étapes de construction nommées existantes de Docker. La combinaison des deux fonctionnalités vous aide à créer des Dockerfiles modulaires qui peuvent être personnalisés au moment de la construction.
Vous pouvez commencer avec plusieurs contextes de construction dès aujourd’hui en mettant à jour vers Docker 20.10.13 ou une version plus récente et en utilisant docker buildx
pour créer vos images. Des distributions BuildKit autonomes sont également disponibles lorsque vous ne souhaitez pas installer l’intégralité de la CLI Docker.