Comment utiliser la commande docker buildx build pour construire et gérer des images

DockerDockerBeginner
Pratiquer maintenant

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Dans ce lab, vous acquerrez une expérience pratique en utilisant la commande docker buildx build pour construire et gérer des images Docker. Vous commencerez par construire une image simple avec les paramètres par défaut, en apprenant à définir les instructions d'image à l'aide d'un Dockerfile.

Au-delà des bases, vous explorerez des fonctionnalités plus avancées telles que l'utilisation d'arguments de build (build arguments) et le ciblage d'étapes spécifiques dans un build multi-étapes (multi-stage build). Vous apprendrez également à gérer efficacement le cache de build pour optimiser les temps de construction en utilisant --cache-from et --cache-to. De plus, le lab vous guidera à travers la construction d'images multi-plateformes et leur envoi vers un registre, et démontrera comment exposer de manière sécurisée des secrets (secrets) et des agents SSH pendant le processus de build.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker(("Docker")) -.-> docker/SystemManagementGroup(["System Management"]) docker(("Docker")) -.-> docker/DockerfileGroup(["Dockerfile"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ImageOperationsGroup -.-> docker/push("Push Image to Repository") docker/ImageOperationsGroup -.-> docker/rmi("Remove Image") docker/ImageOperationsGroup -.-> docker/images("List Images") docker/SystemManagementGroup -.-> docker/login("Log into Docker Registry") docker/DockerfileGroup -.-> docker/build("Build Image from Dockerfile") subgraph Lab Skills docker/run -.-> lab-555045{{"Comment utiliser la commande docker buildx build pour construire et gérer des images"}} docker/push -.-> lab-555045{{"Comment utiliser la commande docker buildx build pour construire et gérer des images"}} docker/rmi -.-> lab-555045{{"Comment utiliser la commande docker buildx build pour construire et gérer des images"}} docker/images -.-> lab-555045{{"Comment utiliser la commande docker buildx build pour construire et gérer des images"}} docker/login -.-> lab-555045{{"Comment utiliser la commande docker buildx build pour construire et gérer des images"}} docker/build -.-> lab-555045{{"Comment utiliser la commande docker buildx build pour construire et gérer des images"}} end

Construire une image simple avec les paramètres par défaut

Dans cette étape, vous apprendrez à construire une image Docker simple en utilisant un Dockerfile. Un Dockerfile est un document texte qui contient toutes les commandes qu'un utilisateur pourrait exécuter en ligne de commande pour assembler une image. Docker peut construire des images automatiquement en lisant les instructions d'un Dockerfile.

Commencez par naviguer vers le répertoire ~/project, qui est votre répertoire de travail pour ce lab.

cd ~/project

Maintenant, créons un Dockerfile simple. Ce Dockerfile définira une image basée sur l'image de base ubuntu et affichera simplement "Hello, Docker!" lorsqu'un conteneur est lancé à partir de cette image.

Utilisez l'éditeur nano pour créer un fichier nommé Dockerfile dans le répertoire ~/project.

nano Dockerfile

Ajoutez le contenu suivant au Dockerfile:

FROM ubuntu:latest
CMD ["echo", "Hello, Docker!"]

Décomposons ce Dockerfile simple :

  • FROM ubuntu:latest : Cette instruction définit l'image de base pour notre nouvelle image. Nous utilisons la dernière version de l'image officielle Ubuntu de Docker Hub.
  • CMD ["echo", "Hello, Docker!"] : Cette instruction spécifie la commande qui sera exécutée lorsqu'un conteneur est démarré à partir de cette image. Dans ce cas, elle exécutera la commande echo avec l'argument "Hello, Docker!".

Enregistrez le fichier en appuyant sur Ctrl + S et quittez l'éditeur nano avec Ctrl + X.

Maintenant que nous avons notre Dockerfile, nous pouvons construire l'image en utilisant la commande docker build. Le . à la fin de la commande indique à Docker de chercher le Dockerfile dans le répertoire courant (~/project). Nous allons également étiqueter l'image avec un nom, par exemple my-hello-image.

docker build -t my-hello-image .

Vous verrez une sortie indiquant que Docker construit l'image couche par couche. Il téléchargera d'abord l'image ubuntu:latest si elle n'est pas déjà présente sur votre système, puis exécutera l'instruction CMD.

Une fois la construction terminée, vous pouvez vérifier que l'image a été créée avec succès en listant les images disponibles avec la commande docker images.

docker images

Vous devriez voir my-hello-image dans la liste.

Enfin, lançons un conteneur à partir de notre nouvelle image pour voir la sortie de l'instruction CMD.

docker run my-hello-image

Vous devriez voir la sortie "Hello, Docker!" s'afficher dans votre terminal. Cela confirme que notre image a été construite correctement et que l'instruction CMD fonctionne comme prévu.

Utiliser des arguments de build et cibler des étapes

Dans cette étape, vous apprendrez à utiliser des arguments de build (ARG) et à cibler des étapes dans votre Dockerfile pour créer des builds plus flexibles et efficaces. Les arguments de build vous permettent de passer des variables au processus de build, tandis que le ciblage d'étapes vous permet de définir plusieurs étapes de build dans un seul Dockerfile et de ne construire qu'une étape spécifique.

Commencez par vous assurer que vous êtes dans le répertoire ~/project.

cd ~/project

Modifions notre Dockerfile existant pour inclure un argument de build et un build multi-étapes simple. Nous allons définir un argument pour un message de salutation et utiliser une deuxième étape pour copier un fichier depuis la première étape.

Ouvrez le Dockerfile avec nano :

nano Dockerfile

Remplacez le contenu existant par :

## Étape 1 : Étape de construction
FROM ubuntu:latest as builder
ARG GREETING="Hello from build argument!"
RUN echo $GREETING > /app/greeting.txt

## Étape 2 : Étape finale
FROM ubuntu:latest
COPY --from=builder /app/greeting.txt /greeting.txt
CMD ["cat", "/greeting.txt"]

Examinons les modifications :

  • ARG GREETING="Hello from build argument!" : Cette instruction définit un argument de build nommé GREETING avec une valeur par défaut. Vous pouvez remplacer cette valeur pendant le build.
  • FROM ubuntu:latest as builder : Démarre la première étape de build et la nomme builder. Utile pour les builds multi-étapes.
  • RUN echo $GREETING > /app/greeting.txt : Dans l'étape builder, cette commande crée un fichier greeting.txt dans /app et y écrit la valeur de l'argument GREETING.
  • FROM ubuntu:latest : Démarre la deuxième étape de build. Ce sera l'image finale par défaut.
  • COPY --from=builder /app/greeting.txt /greeting.txt : Copie le fichier greeting.txt depuis l'étape builder vers le répertoire racine (/) de l'étape actuelle. C'est ainsi qu'on transfère des artefacts entre étapes.
  • CMD ["cat", "/greeting.txt"] : Définit la commande exécutée quand un conteneur est lancé. Elle affichera le contenu de /greeting.txt.

Enregistrez le Dockerfile et quittez nano.

Construisons maintenant l'image avec docker build. Nous utiliserons le flag --build-arg pour passer une valeur personnalisée à l'argument GREETING. Nous taguerons aussi cette image comme my-arg-image.

docker build --build-arg GREETING="Greetings from the command line!" -t my-arg-image .

Observez la sortie. Vous devriez voir le processus de build utiliser l'argument fourni.

Après le build, listez les images pour confirmer la présence de my-arg-image.

docker images

Lancez maintenant un conteneur depuis my-arg-image pour voir le résultat.

docker run my-arg-image

Vous devriez voir "Greetings from the command line!" s'afficher, confirmant que l'argument de build a été utilisé.

Construisons maintenant uniquement l'étape builder. C'est utile pour créer des images intermédiaires contenant des artefacts de build sans l'application finale. Nous utilisons le flag --target pour spécifier l'étape.

docker build --target builder -t my-builder-stage .

Listez à nouveau les images. Vous devriez maintenant voir my-builder-stage en plus de my-arg-image.

docker images

Lancer un conteneur depuis my-builder-stage ne produira pas la même sortie que my-arg-image car l'instruction CMD de l'étape finale n'est pas incluse. Essayons de le lancer pour voir (il démarrera et s'arrêtera probablement rapidement car il n'y a pas de commande par défaut).

docker run my-builder-stage

Ceci démontre comment le ciblage d'étapes vous permet de contrôler quelle partie de votre Dockerfile est construite dans une image.

Gérer le cache de build avec --cache-from et --cache-to

Dans cette étape, vous apprendrez à gérer le cache de build Docker en utilisant les flags --cache-from et --cache-to. Le cache de build peut accélérer considérablement les builds ultérieurs en réutilisant les couches des builds précédents. --cache-from vous permet de spécifier une image à utiliser comme source de cache, et --cache-to vous permet d'exporter le cache de build vers un emplacement spécifié (comme un registry ou un répertoire local).

Commencez par vous assurer que vous êtes dans le répertoire ~/project.

cd ~/project

Modifions légèrement notre Dockerfile pour simuler un changement qui invaliderait normalement le cache. Nous ajouterons une simple instruction RUN.

Ouvrez le Dockerfile avec nano :

nano Dockerfile

Ajoutez la ligne suivante après l'instruction ARG dans l'étape builder :

RUN echo "Adding a new layer"

Le Dockerfile mis à jour devrait ressembler à ceci :

## Stage 1: Builder stage
FROM ubuntu:latest as builder
ARG GREETING="Hello from build argument!"
RUN echo "Adding a new layer"
RUN echo $GREETING > /app/greeting.txt

## Stage 2: Final stage
FROM ubuntu:latest
COPY --from=builder /app/greeting.txt /greeting.txt
CMD ["cat", "/greeting.txt"]

Enregistrez le Dockerfile et quittez nano.

Maintenant, reconstruisons l'image sans utiliser d'options de cache spécifiques. Docker utilisera automatiquement le cache local s'il est disponible.

docker build -t my-cached-image .

Vous devriez voir que certaines couches sont reconstruites à partir de zéro car nous avons ajouté une nouvelle instruction, invalidant le cache pour les instructions suivantes.

Simulons maintenant un scénario où vous souhaiteriez utiliser une image précédemment construite comme source de cache, peut-être depuis un registry ou un autre build. À des fins de démonstration, nous utiliserons l'image my-cached-image que nous venons de construire comme source de cache pour un nouveau build.

D'abord, apportons une autre petite modification au Dockerfile pour simuler un autre changement.

Ouvrez le Dockerfile :

nano Dockerfile

Modifiez le message dans la nouvelle instruction RUN :

RUN echo "Adding another new layer"

Le Dockerfile mis à jour devrait ressembler à ceci :

## Stage 1: Builder stage
FROM ubuntu:latest as builder
ARG GREETING="Hello from build argument!"
RUN echo "Adding another new layer"
RUN echo $GREETING > /app/greeting.txt

## Stage 2: Final stage
FROM ubuntu:latest
COPY --from=builder /app/greeting.txt /greeting.txt
CMD ["cat", "/greeting.txt"]

Enregistrez et quittez nano.

Maintenant, reconstruisons l'image, mais cette fois en utilisant le flag --cache-from pour spécifier my-cached-image comme source de cache.

docker build --cache-from my-cached-image -t my-cached-image-from .

Vous devriez observer que Docker tente d'utiliser les couches de my-cached-image. La couche correspondant à la première instruction RUN sera probablement reconstruite car l'instruction a changé, mais les couches suivantes pourraient être récupérées du cache si elles correspondent.

Le flag --cache-to est utilisé pour exporter le cache de build. Ceci est particulièrement utile dans les pipelines CI/CD pour partager le cache entre les builds. Pour utiliser --cache-to, vous avez généralement besoin d'un driver de build qui prend en charge l'exportation de cache, comme le driver docker-container.

D'abord, installons Docker Compose, souvent utilisé avec buildx.

sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

Maintenant, créons une instance de builder buildx.

docker buildx create --use

Construisons maintenant l'image et exportons le cache vers un répertoire local. Nous utiliserons l'exportateur de cache local.

docker buildx build --cache-to type=local,dest=./build-cache -t my-exported-cache-image . --load
  • docker buildx build : Utilise l'outil buildx pour la construction
  • --cache-to type=local,dest=./build-cache : Exporte le cache vers un répertoire local nommé build-cache
  • -t my-exported-cache-image : Tagge l'image résultante
  • . : Spécifie le contexte de build (répertoire courant)
  • --load : Charge l'image construite dans le cache d'images Docker local

Vous devriez voir une sortie indiquant la construction et l'exportation du cache. Un répertoire build-cache sera créé dans votre répertoire ~/project.

Simulons maintenant un environnement de build propre et essayons de construire en utilisant le cache exporté. D'abord, supprimons les images que nous avons construites.

docker rmi my-cached-image my-cached-image-from my-exported-cache-image

Maintenant, reconstruisons l'image, cette fois en utilisant le cache exporté comme source.

docker buildx build --cache-from type=local,src=./build-cache -t my-imported-cache-image . --load
  • --cache-from type=local,src=./build-cache : Importe le cache depuis le répertoire local build-cache

Vous devriez observer que Docker utilise les couches du cache exporté, accélérant considérablement le processus de build par rapport à une construction à partir de zéro.

Construire des images multi-plateformes et les pousser vers un registry

Dans cette étape, vous apprendrez à construire des images Docker pour plusieurs architectures (comme linux/amd64 et linux/arm64) et à les pousser vers un registry de conteneurs. La construction d'images multi-plateformes est essentielle pour garantir que vos applications peuvent s'exécuter sur différents types de matériel. Nous utiliserons Docker Buildx, que vous avez initialisé à l'étape précédente.

Commencez par vous assurer que vous êtes dans le répertoire ~/project.

cd ~/project

Nous utiliserons notre Dockerfile existant pour cette étape. Construisons une image pour les plateformes linux/amd64 et linux/arm64. Nous taggerons l'image avec un nom et une version, par exemple your-dockerhub-username/my-multi-platform-image:latest. Remplacez your-dockerhub-username par votre nom d'utilisateur Docker Hub réel. Si vous n'avez pas de compte Docker Hub, vous pouvez en créer un gratuitement.

Pour construire pour plusieurs plateformes, nous utilisons le flag --platform avec docker buildx build. Nous devons également utiliser le flag --push pour pousser la liste de manifestes et les images résultantes vers un registry.

docker buildx build --platform linux/amd64,linux/arm64 -t your-dockerhub-username/my-multi-platform-image:latest . --push

Note : Cette commande nécessitera que vous soyez connecté à Docker Hub si ce n'est déjà fait. Vous pouvez vous connecter en utilisant la commande docker login dans une session terminal séparée si nécessaire.

docker login

Entrez votre nom d'utilisateur et mot de passe Docker Hub lorsque demandé.

Après vous être connecté, exécutez à nouveau la commande docker buildx build.

Le processus de construction prendra plus de temps qu'une construction mono-plateforme car il construit l'image pour chaque architecture spécifiée. Une fois la construction terminée, Buildx créera une liste de manifestes référençant les images pour chaque plateforme et poussera le tout vers votre dépôt Docker Hub spécifié.

Vous pouvez vérifier que l'image multi-plateforme a été poussée en visitant votre dépôt Docker Hub dans un navigateur web. Vous devriez voir my-multi-platform-image avec le tag latest, et sous l'onglet "Tags", vous devriez voir qu'il prend en charge plusieurs architectures.

Alternativement, vous pouvez utiliser la commande docker buildx imagetools inspect pour inspecter la liste de manifestes que vous venez de pousser. Remplacez your-dockerhub-username par votre nom d'utilisateur.

docker buildx imagetools inspect your-dockerhub-username/my-multi-platform-image:latest

La sortie montrera la liste de manifestes et les différentes images (avec leurs architectures respectives) auxquelles elle fait référence.

Ceci démontre comment construire et pousser des images pouvant s'exécuter sur différentes architectures CPU, rendant vos images Docker plus polyvalentes.

Exposer des secrets et l'agent SSH au build

Dans cette étape, vous apprendrez comment exposer de manière sécurisée des secrets et votre agent SSH au processus de build Docker en utilisant Buildx. Ceci est crucial pour les scénarios où votre build a besoin d'accéder à des dépôts privés, installer des paquets privés ou interagir avec des services externes nécessitant une authentification, sans intégrer d'informations sensibles directement dans votre Dockerfile.

Commencez par vous assurer que vous êtes dans le répertoire ~/project.

cd ~/project

Nous allons modifier notre Dockerfile pour démontrer comment utiliser un secret pendant le build. Pour cet exemple, nous créerons un fichier secret factice et lirons son contenu pendant le build.

Créez un fichier nommé mysecret.txt dans le répertoire ~/project avec un contenu secret.

echo "This is a secret message!" > ~/project/mysecret.txt

Maintenant, ouvrez le Dockerfile avec nano :

nano Dockerfile

Ajoutez une nouvelle instruction RUN dans l'étape builder qui utilise le flag --mount=type=secret pour accéder au secret.

## Stage 1: Builder stage
FROM ubuntu:latest as builder
ARG GREETING="Hello from build argument!"
RUN echo "Adding another new layer"
RUN echo $GREETING > /app/greeting.txt
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret > /app/secret_content.txt

## Stage 2: Final stage
FROM ubuntu:latest
COPY --from=builder /app/greeting.txt /greeting.txt
COPY --from=builder /app/secret_content.txt /secret_content.txt
CMD ["cat", "/greeting.txt", "/secret_content.txt"]

Comprendons la nouvelle instruction :

  • RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret > /app/secret_content.txt : Cette instruction monte un secret dans le conteneur de build.
    • --mount=type=secret : Spécifie que nous montons un secret.
    • id=mysecret : C'est l'ID du secret que nous fournirons pendant le build.
    • cat /run/secrets/mysecret : Dans le conteneur de build, le secret est disponible à /run/secrets/mysecret. Nous utilisons cat pour lire son contenu.
    • > /app/secret_content.txt : Nous redirigeons le contenu secret vers un fichier nommé secret_content.txt dans le répertoire /app de l'étape builder.

Nous avons également ajouté une instruction COPY dans l'étape finale pour copier le fichier secret_content.txt depuis l'étape builder.

Enregistrez le Dockerfile et quittez nano.

Maintenant, construisez l'image en utilisant docker buildx build et fournissez le secret avec le flag --secret.

docker buildx build --secret id=mysecret,src=~/project/mysecret.txt -t my-secret-image . --load
  • --secret id=mysecret,src=~/project/mysecret.txt : Ce flag fournit le secret au build.
    • id=mysecret : Correspond à l'ID spécifié dans le Dockerfile.
    • src=~/project/mysecret.txt : Spécifie le chemin vers le fichier secret sur votre machine locale.

Le processus de build aura maintenant accès au contenu de mysecret.txt pendant l'exécution de l'instruction RUN --mount=type=secret.... Le contenu secret n'est pas stocké dans les couches finales de l'image.

Une fois le build terminé, exécutez un conteneur à partir de l'image.

docker run my-secret-image

Vous devriez voir à la fois le message de salutation et le contenu de votre fichier secret affichés dans la console.

Maintenant, démontrons comment exposer votre agent SSH au build. Ceci est utile pour cloner des dépôts Git privés pendant le processus de build.

D'abord, assurez-vous que votre agent SSH est actif et a votre clé chargée. Vous pouvez généralement vérifier ceci avec ssh-add -l. Si votre agent n'est pas actif ou votre clé n'est pas ajoutée, vous devrez peut-être démarrer l'agent et ajouter votre clé.

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa ## Remplacez par le chemin de votre clé SSH si différent

Maintenant, modifiez le Dockerfile pour utiliser l'agent SSH. Nous ajouterons une instruction RUN qui tente de cloner un dépôt privé (inexistant) en utilisant SSH.

Ouvrez le Dockerfile :

nano Dockerfile

Ajoutez une nouvelle instruction RUN dans l'étape builder qui utilise le flag --mount=type=ssh.

## Stage 1: Builder stage
FROM ubuntu:latest as builder
ARG GREETING="Hello from build argument!"
RUN echo "Adding another new layer"
RUN echo $GREETING > /app/greeting.txt
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret > /app/secret_content.txt
RUN --mount=type=ssh git clone [email protected]:your-username/your-private-repo.git || echo "Skipping git clone as this is a demo"

## Stage 2: Final stage
FROM ubuntu:latest
COPY --from=builder /app/greeting.txt /greeting.txt
COPY --from=builder /app/secret_content.txt /secret_content.txt
CMD ["cat", "/greeting.txt", "/secret_content.txt"]

Note : Remplacez your-username/your-private-repo.git par un placeholder pour une URL de dépôt privé. La partie || echo "Skipping git clone as this is a demo" est ajoutée pour que le build ne échoue pas si le dépôt n'existe pas ou si vous n'avez pas accès.

Enregistrez le Dockerfile et quittez nano.

Maintenant, construisez l'image en utilisant docker buildx build et fournissez l'accès à votre agent SSH avec le flag --ssh.

docker buildx build --ssh default -t my-ssh-image . --load
  • --ssh default : Ce flag expose votre agent SSH par défaut au build.

Pendant le build, l'instruction RUN --mount=type=ssh... pourra utiliser votre agent SSH pour s'authentifier auprès du serveur Git.

Une fois le build terminé, vous pouvez exécuter l'image, bien que le résultat sera le même qu'avant puisque l'opération de clonage Git a probablement été ignorée.

docker run my-ssh-image

Ceci démontre comment utiliser de manière sécurisée des secrets et votre agent SSH pendant le processus de build Docker avec Buildx, empêchant les informations sensibles d'être intégrées dans vos images.

Résumé

Dans ce lab, vous avez appris les fondamentaux de la construction d'images Docker à l'aide d'un Dockerfile. Vous avez commencé par créer un simple Dockerfile définissant une image basée sur Ubuntu et exécutant une commande basique. Vous avez ensuite utilisé la commande docker build pour construire cette image, comprenant comment Docker traite les instructions du Dockerfile couche par couche et comment tagger l'image résultante.

En approfondissant les bases, vous avez exploré des fonctionnalités plus avancées de la commande docker buildx build. Cela incluait l'utilisation d'arguments de build pour passer des valeurs dynamiques au processus de construction et l'exploitation d'étapes cibles dans un build multi-étapes pour optimiser la taille de l'image et le temps de build. Vous avez également appris à gérer efficacement le cache de build en utilisant --cache-from et --cache-to pour accélérer les builds ultérieurs. De plus, vous avez acquis de l'expérience dans la construction d'images multi-plateformes, permettant à vos images de s'exécuter sur différentes architectures, et dans le push de ces images multi-plateformes vers un registry de conteneurs. Enfin, vous avez découvert comment exposer de manière sécurisée des secrets et utiliser un agent SSH pendant le processus de build, améliorant ainsi la sécurité et la flexibilité de vos constructions d'images.