Comment utiliser Docker Buildx Bake pour créer des pipelines de construction d'images complexes

Publié: 2022-08-10

Graphique montrant le logo Docker

Le groupe de commandes docker buildx utilise BuildKit pour exposer les fonctionnalités avancées de création d'image. Les builds préparés sont une fonctionnalité de haut niveau qui peut être utilisée pour définir des pipelines de build automatisés. Ils vous permettent de produire plusieurs images à partir d'une seule opération de construction.

Les workflows prédéfinis sont utiles lorsque vous souhaitez publier différentes variantes de vos images ou créer plusieurs projets liés en parallèle. Dans cet article, nous aborderons les principales fonctionnalités de docker buildx bake et comment vous pouvez les utiliser pour rationaliser les builds complexes.

Commencer

La commande docker buildx bake exécute plusieurs « cibles » de construction qui produisent chacune une image de conteneur. Les cibles s'exécutent en parallèle dans la mesure du possible pour optimiser les performances. Les cibles peuvent également référencer directement les prédécesseurs pour créer des pipelines séquentiels.

Les cibles de construction peuvent être définies à l'aide de plusieurs mécanismes différents, y compris les fichiers Docker Compose existants. Buildx construira automatiquement toutes les images identifiées dans le fichier.

Des fonctionnalités plus avancées sont exposées lorsque vous répertoriez les cibles de build dans des fichiers JSON ou HCL. Ceux-ci prennent en charge les variables, les fonctions et l'interpolation de valeur pour personnaliser vos builds.

La commande buildx bake recherche les fichiers suivants dans l'ordre :

  • docker-compose.yml
  • docker-compose.yaml
  • docker-bake.json
  • docker-bake.override.json
  • docker-bake.hcl
  • docker-bake.override.hcl

Vous pouvez spécifier un fichier différent avec l'indicateur de commande -f .

Construire des cibles

Les cibles de build encapsulent toute la configuration liée à votre build. Ils comprennent des détails tels que

  • le chemin vers le Dockerfile à construire
  • construire des chemins de contexte, définissant le contenu disponible dans votre Dockerfile
  • balises et étiquettes à attacher aux images de sortie
  • les plateformes pour produire des images.

Une liste complète des champs de configuration pris en charge est disponible dans la documentation. Auparavant, vous avez peut-être fourni ces paramètres sous forme d'indicateurs de ligne de commande à docker buildx build (ou même docker build ), vous obligeant à vous souvenir des valeurs correctes à chaque fois. Avec buildx bake , vous pouvez utiliser de manière fiable les mêmes valeurs en les définissant dans votre fichier de cuisson contrôlé par version.

Voici un exemple simple d'une commande docker-bake.hcl qui définit une cible de construction unique :

 target "default" { dockerfile = "app/Dockerfile" contexts = { app = "app/src" shared = "shared-components/src" } tags = ["my-app:latest", "docker.io/my-org/my-app:latest"] }

L'exécution docker buildx bake avec ce fichier de cuisson chargera l' app/Dockerfile Dockerfile à partir de votre répertoire de travail. Il aura accès aux répertoires app/src et shared-components/src en tant que contextes de construction. L'image qui est produite se verra attribuer deux balises.

La cible default est créée automatiquement lorsque vous exécutez docker buildx bake . Vous pouvez également définir des cibles nommées pouvant être créées à la demande :

 target "app" { // ... }
 $ docker buildx bake app

Utiliser plusieurs cibles

Vous pouvez construire une autre image simultanément en la définissant comme une nouvelle cible dans votre fichier bake :

 group "default" { targets = ["app", "api"] } target "app" { dockerfile = "app/Dockerfile" contexts = { app = "app/src" shared = "shared-components/src" } tags = ["my-app:latest", "docker.io/my-org/my-app:latest"] } target "api" { dockerfile = "api/Dockerfile" contexts = { src = "api/src" } tags = ["my-api:latest", "docker.io/my-org/my-api:latest"] }

Ces images peuvent être créées simultanément car elles sont imbriquées dans un groupe. Les images d' api et app seront construites en parallèle chaque fois que vous exécuterez la commande docker buildx bake car le groupe default est automatiquement sélectionné. Vous pouvez utiliser des groupes nommés de la même manière que dans l'exemple de cibles nommées ci-dessus.

Construire l'héritage cible

Les cibles de génération peuvent hériter les unes des autres pour réutiliser la configuration. Un scénario où cela peut être utile concerne les images qui doivent être personnalisées pour différents environnements. Vous souhaiterez peut-être ajouter des fichiers de configuration supplémentaires aux variantes d'image destinées à une utilisation en développement. Voici un docker-bake.hcl qui illustre ce modèle :

 group "default" { targets = ["backend", "backend-dev"] } target "backend" { dockerfile = "backend/Dockerfile" contexts = { src = "api/src" config = "api/config" } tags = ["backend:latest"] } target "backend-dev" { inherits = ["backend"] contexts = { config = "api/config-dev" } tags = ["backend:dev"] }

La cible backend-dev hérite de toutes les propriétés de la cible backend mais remplace le contexte de config et applique une balise différente.

Vous pouvez prévisualiser la structure du fichier fusionné en exécutant la commande bake avec l'indicateur --print :

 $ docker buildx bake --print ... "backend-dev": { "context": ".", "contexts": { "config": "api/config-dev", "src": "api/src" }, "dockerfile": "backend/Dockerfile", "tags": [ "backend:dev" ] } ...

Utilisation d'une cible précédente comme image de base

Parfois, vous souhaiterez peut-être qu'une cible de génération utilise l'image créée par une cible précédente comme sa propre base. Il s'agit d'une alternative aux builds en plusieurs étapes qui peuvent être utilisées lorsque vos Dockerfiles dépendent les uns des autres mais ne peuvent pas être fusionnés, peut-être parce qu'ils existent dans différents projets.

 group "default" { targets = ["org-base-image", "api"] } target "org-base-image" { dockerfile = "docker-base/Dockerfile" tags = ["org-base-image:latest"] } target "api" { dockerfile = "api/Dockerfile" contexts = { base = "target:org-base-image" } tags = ["api:latest"] }

L'exemple construit d'abord la cible org-base-image . Cela peut contenir certains utilitaires communs aux charges de travail conteneurisées de votre organisation. La cible api est ensuite construite avec la sortie de la cible org-base-image accessible en tant que contexte de construction de base . L'API Dockerfile peut désormais référencer du contenu dans l'image de base :

 COPY --from=base /utilities/example /usr/bin/example-utility

Il s'agit d'un modèle puissant qui vous permet de créer des liens de dépendance entre les images tout en conservant des Dockerfiles séparés.

Remplacement des propriétés des cibles au moment de la construction

La commande docker buildx bake vous permet de remplacer les propriétés de vos cibles lorsque vous exécutez votre build :

 $ docker buildx bake --set api.dockerfile="api/Dockerfile-dev"

Cet exemple modifie le Dockerfile de la cible api . Le caractère générique * est pris en charge lors de l'identification de la cible à modifier. * seul sélectionne chaque cible tandis que api* modifiera toutes les cibles commençant par api .

Définition de variables

Les fichiers HCL peuvent définir des variables que vous pouvez référencer dans vos cibles de génération. utilisez un bloc variable pour les configurer :

 variable "TAG" { default = "latest" } group "default" { targets = ["app"] } target "app" { dockerfile = "src/Dockerfile" tags = ["my-app:${TAG}"] }

L'exécution docker buildx bake avec cette configuration marquera la cible de l' app comme my-app:latest . Vous pouvez modifier la valeur de la variable TAG en définissant une variable d'environnement avant d'exécuter la commande :

 $ TAG=v1 docker buildx bake

Vous pouvez utiliser toutes les capacités d'interpolation et de comparaison de variables du langage HCL pour rendre vos cibles de construction réutilisables. Des fonctions sont également disponibles pour analyser et transformer vos valeurs.

Sommaire

Les builds Baked Buildx vous permettent d'encapsuler la configuration de build d'image en tant que « cibles » définies dans un fichier. Lorsque vous exécutez buildx bake , les images de toutes les cibles référencées sont créées en parallèle.

Les cibles peuvent hériter les unes des autres et dépendre les unes des autres. Vous pouvez également utiliser des variables et des fonctions pour créer des pipelines de build hautement complexes et configurables.

La commande docker buildx bake est une opération de haut niveau qui n'est pas nécessaire dans tous les workflows. Vous n'avez pas besoin de l'utiliser lorsque vous créez des images simples sans dépendances entre projets. L'utilisation de docker compose build est une meilleure alternative pour la plupart des cas d'utilisation qui conserve la configuration de build dans votre fichier docker-compose.yml . Le passage aux builds préinstallés doit être envisagé lorsque vous créez plusieurs images simultanément à l'aide de différentes variables, plates-formes, contextes de build et remplacements de configuration.