Comment démarrer avec l'API Docker Engine
Agence web » Actualités du digital » Comment accélérer les builds Docker et optimiser la mise en cache avec « COPY –link »

Comment accélérer les builds Docker et optimiser la mise en cache avec « COPY –link »

COPY --link est une nouvelle fonctionnalité de BuildKit qui pourrait considérablement accélérer la création de vos images Docker. Il fonctionne en copiant des fichiers dans des calques d’image indépendants qui ne dépendent pas de la présence de leurs prédécesseurs. Vous pouvez ajouter du nouveau contenu aux images sans même que l’image de base n’existe sur votre système.

Cette fonctionnalité a été ajoutée dans le cadre de Buildx v0.8 en mars 2022. Elle est incluse dans la version 20.10.14 de la CLI Docker, vous devriez donc déjà y avoir accès si vous exécutez la dernière version.

Dans cet article, nous allons montrer ce que --link fait et expliquer comment cela fonctionne. Nous examinerons également certaines des situations dans lesquelles il ne devrait pas être utilisé.

--link est un nouvel argument facultatif pour le Dockerfile existant COPY instruction. Il modifie le fonctionnement des copies en créant un nouveau calque d’instantané à chaque fois que vous l’utilisez.

Habituel COPY Les instructions ajoutent des fichiers à la couche qui les précède dans le Dockerfile. Le contenu de cette couche doit exister sur votre disque pour que le nouveau contenu puisse être fusionné :

FROM alpine
COPY my-file /my-file
COPY another-file /another-file

Le Dockerfile ci-dessus copie my-file dans le calque produit par la commande précédente. Après le FROM instruction, l’image se compose du contenu d’Alpine :

bin/
dev/
etc/
...

La première COPY l’instruction produit une image qui comprend tout d’Alpine, ainsi que le my-file dossier:

my-file
bin/
dev/
etc/
...

Et le deuxième COPY l’instruction ajoute another-file au dessus de cette image :

another-file
my-file
bin/
dev/
etc/
...

La couche produite par chaque instruction comprend tout ce qui l’a précédée, ainsi que tout ce qui a été ajouté récemment. À la fin de la construction, Docker utilise un processus différent pour déterminer les modifications au sein de chaque couche. Le blob d’image final contient uniquement les fichiers qui ont été ajoutés à chaque étape d’instantané, mais cela n’est pas reflété dans le processus d’assemblage lors de la construction.

« -link » modifie COPY pour créer un nouveau système de fichiers autonome à chaque utilisation. Au lieu de copier les nouveaux fichiers au-dessus du calque précédent, ils sont envoyés à un emplacement complètement différent pour devenir un calque indépendant. Les calques sont ensuite liés entre eux pour produire l’image finale.

Changeons l’exemple Dockerfile à utiliser --link:

FROM alpine
COPY --link my-file /my-file
COPY --link another-file /another-file

Le résultat de la FROM l’instruction est inchangée – elle donne la couche Alpine, avec tout le contenu de cette image :

bin/
dev/
etc/
...

La première COPY l’instruction a un effet sensiblement différent. Cette fois, une autre couche indépendante est créée. C’est un nouveau système de fichiers contenant uniquement my-file:

my-file

Puis le deuxième COPY l’instruction crée un autre nouvel instantané avec seulement another-file:

another-file

Une fois la construction terminée, Docker stocke ces instantanés indépendants en tant que nouvelles archives de couches (tarballs). Les archives tar sont reliées à la chaîne de couches précédentes, constituant l’image finale. Il s’agit des trois instantanés fusionnés, ce qui donne un système de fichiers qui correspond à celui d’origine lors de la création des conteneurs :

my-file
another-file
bin/
dev/
etc/
...

Cette image du projet BuildKit illustre les différences entre les deux approches.

Image du blog Docker montrant les différences entre "COPY" et "COPY --link"

COPY --link n’est disponible que lorsque vous utilisez BuildKit pour créer vos images. Soit exécuter votre build avec docker buildx --create Ou utiliser docker build avec le DOCKER_BUILDKIT=1 ensemble de variables d’environnement.

Vous devez également vous inscrire à la syntaxe Dockerfile v1.4 en utilisant un commentaire en haut de votre fichier :

# syntax=docker/dockerfile:1.4
FROM alpine:latest
COPY --link my-file /my-file
COPY --link another-file /another-file

Vous pouvez désormais créer votre image avec la prise en charge des copies liées :

DOCKER_BUILDKIT=1 docker build -t my-image:latest .

Images construites à partir de Dockerfiles à l’aide COPY --link peut être utilisé comme n’importe quel autre. Vous pouvez démarrer un conteneur avec docker run et poussez-les directement vers les registres. La --link L’indicateur n’affecte que la manière dont le contenu est ajouté aux calques d’image lors de la construction.

Pourquoi les copies liées sont importantes

En utilisant le --link flag autorise la réutilisation des caches de construction même lorsque le contenu que vous COPY dans les changements. De plus, les builds peuvent se terminer sans même que leur image de base n’existe sur votre machine.

Revenant à l’exemple ci-dessus, standard COPY comportement exige la alpine image doit exister sur votre hôte Docker avant que le nouveau contenu puisse être ajouté. L’image sera téléchargée automatiquement lors de la construction si vous ne l’avez pas déjà extraite.

Avec les copies liées, Docker n’a pas besoin de alpine contenu de l’image. Il tire le alpine manifeste, crée de nouvelles couches indépendantes pour les fichiers copiés, puis crée un manifeste révisé qui relie les couches à celles fournies par alpine. Le contenu de la alpine image – ses blobs de couches – ne sera téléchargée que si vous démarrez un conteneur à partir de votre nouvelle image ou si vous l’exportez dans une archive tar. Lorsque vous poussez l’image vers un registre, ce registre stocke ses nouvelles couches et acquiert à distance le alpine ceux.

Cette fonctionnalité facilite également les rebases d’images efficaces. Peut-être distribuez-vous actuellement une image Docker à l’aide de la dernière version d’Ubuntu 20.04 LTS :

FROM golang AS build
...
RUN go build -o /app .

FROM ubuntu:20.04
COPY --link --from=build /app /bin/app
ENTRYPOINT ["/bin/app"]

Vous pouvez créer l’image avec la mise en cache activée à l’aide de BuildKit --cache-to drapeau. La inline cache stocke les données du cache de build dans l’image de sortie, où elles peuvent être réutilisées dans les builds suivants :

docker buildx build --cache-to type=inline -t example-image:20.04 .

Supposons maintenant que vous souhaitiez fournir une image basée sur le prochain LTS après sa sortie, Ubuntu 22.04 :

FROM golang AS build
...
RUN go build -o /app .

FROM ubuntu:22.04
COPY --link --from=build /app /bin/app
ENTRYPOINT ["/bin/app"]

Reconstruisez l’image à l’aide des données de cache intégrées dans la version d’origine :

docker buildx build --cache-from example-image:20.04 -t example-image:22.04 .

La construction se terminera presque instantanément. À l’aide des données mises en cache de l’image existante, Docker peut vérifier les fichiers nécessaires à la création /app n’ont pas changé. Cela signifie que le cache de la couche indépendante créée par le COPY l’instruction reste valable. Comme cette couche ne dépend d’aucune autre, la ubuntu:22.04 l’image ne sera pas tirée non plus. Docker relie simplement la couche d’instantané contenant /bin/app dans un nouveau manifeste au sein du ubuntu:22.04 chaîne de couches. La couche d’instantané est effectivement « rebasée » sur une nouvelle image parente, sans qu’aucune opération de système de fichiers ne se produise.

Le modèle optimise également les builds en plusieurs étapes où des changements peuvent se produire entre n’importe laquelle des étapes :

FROM golang AS build
RUN go build -o /app .

FROM config-builder AS config
RUN generate-config --out /config.yaml

FROM ubuntu:latest
COPY --link --from=config /config.yaml build.conf
COPY --link --from=build /app /bin/app

Sans pour autant --linktoute modification de la valeur générée config.yaml causes ubuntu:latest à extraire et le fichier à copier. Le binaire doit ensuite être recompilé car son cache est invalidé par les modifications du système de fichiers. Avec les copies liées, une modification de config.yaml permet à la construction de continuer sans tirer ubuntu:latest ou recompiler le binaire. La couche d’instantané avec build.conf inside est simplement remplacé par une nouvelle version indépendante de toutes les autres couches.

Quand ne pas l’utiliser

Il existe certaines situations où le --link flag ne fonctionnera pas correctement. Comme il copie les fichiers dans un nouveau calque, au lieu de les ajouter au-dessus du précédent, vous ne pouvez pas utiliser de références ambiguës comme chemin de destination :

COPY --link my-file /data

Avec un habitué COPY instruction, my-file sera copié dans /data/my-file si /data existe déjà en tant que répertoire dans l’image. Avec --linkle système de fichiers de la couche cible sera toujours vide, donc my-file est écrit à /data.

La même considération s’applique à la résolution des liens symboliques. Standard COPY résout automatiquement les chemins de destination qui sont des liens symboliques dans l’image. Lorsque vous utilisez --linkce comportement n’est pas pris en charge car le lien symbolique n’existera pas dans la couche indépendante de la copie.

Il est recommandé de commencer à utiliser --link partout où ces limitations ne s’appliquent pas. L’adoption de cette fonctionnalité accélérera vos builds et rendra la mise en cache plus puissante. Si vous ne pouvez pas supprimer immédiatement les chemins de destination ambigus ou liés symboliquement, vous pouvez continuer à utiliser les COPY instruction. C’est à cause de ces modifications rétrocompatibles que --link est un indicateur facultatif, au lieu de la nouvelle valeur par défaut.

Sommaire

BuildKit COPY --link est une nouvelle fonctionnalité Dockerfile qui peut rendre les builds plus rapides et plus efficaces. Les images utilisant des copies liées n’ont pas besoin d’extraire les calques précédents pour que les fichiers puissent y être copiés. Docker crée une nouvelle couche indépendante pour chaque COPY à la place, puis relie ces couches dans la chaîne.

Vous pouvez commencer à utiliser des copies liées dès maintenant si vous créez des images avec BuildKit et la dernière version de Buildx ou Docker CLI. L’adoption de « –link » est une nouvelle étape de construction Docker des meilleures pratiques, à condition que vous ne soyez pas affecté par les modifications de la résolution du chemin de destination qu’elle nécessite.

★★★★★