Simplifiez vos Constructions d'Images avec bake
Mise à jour :
Docker Bake est une fonctionnalité puissante et flexible intégrée à Docker
Buildx, conçue pour simplifier et orchestrer la construction d’images
Docker complexes. Contrairement à
la commande docker build
, qui est souvent linéaire et nécessite des scripts
séparés pour gérer plusieurs builds, Docker Bake permet de définir des recettes
de build dans un fichier de configuration unique.
Comprendre Docker Buildx
Docker Buildx est un outil avancé qui étend les capacités de la commande
classique docker build
. Il permet de créer des images pour différentes
architectures, de gérer des multiples contextes et d’utiliser des
fonctionnalités avancées comme les caches de build. Buildx est conçu pour
améliorer les workflows de build en apportant plus de flexibilité et de
contrôle. Docker Bake, en tant qu’extension de Buildx, tire parti de ces
fonctionnalités pour orchestrer des builds complexes via des fichiers de
configuration.
Pour plus de détails sur Docker Buildx, vous pouvez consulter mon guide .
Différence entre Docker Compose et Docker Bake
Il est important de comprendre que Docker Compose et Docker Bake sont conçus pour des tâches fondamentalement différentes dans l’écosystème Docker. Docker Compose est un outil utilisé pour définir et gérer des applications multi-conteneurs. Il permet de décrire la manière dont plusieurs services interagissent et sont déployés ensemble dans un environnement orchestré.
En revanche, Docker Bake se concentre uniquement sur la construction d’images Docker. Il permet de centraliser les configurations de build dans un fichier unique, orchestrant ainsi des processus de build complexes de manière plus efficace. Par exemple, alors que Docker Compose vous permet de spécifier que vous avez besoin d’une base de données et d’un service web pour fonctionner ensemble, Docker Bake vous permet de définir comment ces services sont construits, en précisant les instructions pour créer les images nécessaires.
Installation et configuration de Docker Bake
Pour commencer à utiliser Docker Bake, il est nécessaire de configurer Docker Buildx, qui est le moteur sous-jacent de Bake. Docker Buildx est inclus dans Docker Desktop, mais il peut être activé manuellement si vous utilisez Docker en ligne de commande.
Un petit contrôle :
Si vous n’avez pas de builder, reportez-vous à ma documentation.
Structure et syntaxe des fichiers Bake
Les fichiers de configuration Bake définissent comment Docker Bake doit
orchestrer vos builds. Par défaut, Docker Bake cherche le fichier de
configuration en suivant un ordre précis : il commence par compose.yaml
,
compose.yml
et docker-compose.yml
, avant de chercher des fichiers
spécifiques à Bake comme docker-bake.json
et docker-bake.hcl
. Cette
flexibilité permet d’utiliser des configurations existantes tout en tirant parti
des fonctionnalités avancées de Bake.
Formats de fichiers supportés
Docker Bake prend en charge plusieurs formats de fichiers pour la configuration :
- HCL : que nous utiliserons dans cette documentation
- JSON
- YAML
Exemple de fichier HCL pour Docker Bake :
Ordre de recherche par défaut
Docker Bake utilise l’ordre suivant pour trouver automatiquement les fichiers de configuration :
- compose.yaml
- compose.yml
- docker-compose.yml
- docker-compose.yaml
- docker-bake.json
- docker-bake.override.json
- docker-bake.hcl
- docker-bake.override.hcl
Si vous souhaitez spécifier explicitement le fichier à utiliser, vous pouvez le
faire avec l’option --file
lors de l’exécution de la commande docker buildx bake
:
Cette flexibilité permet de structurer vos projets comme vous le souhaitez, tout en garantissant que Docker Bake trouve et utilise la bonne configuration pour orchestrer vos builds.
Définition des cibles de build
Les cibles de build dans Docker Bake permettent de structurer et d’organiser vos processus de construction en définissant des configurations spécifiques pour chaque image Docker à construire. Chaque cible peut inclure des éléments tels que le contexte, le Dockerfile, des tags pour les images, des arguments de build et bien plus encore.
Voici un exemple de cibles dans un fichier HCL :
Dans cet exemple, deux cibles distinctes sont définies pour la construction des
images frontend et backend. La première cible construit une image pour
le frontend à partir du répertoire ./frontend
, en utilisant un fichier
Dockerfile situé dans
ce même répertoire et lui assigne le tag myapp/frontend:latest
. La seconde
cible configure une image backend en utilisant le contexte ./backend
, avec un
argument de build NODE_ENV
défini sur “production” et assigne le tag
myapp/backend:latest
.
Une fois les cibles définies, vous pouvez les exécuter simultanément ou individuellement en utilisant Docker Bake. Cela permet d’optimiser le temps de build en parallèle, surtout lorsque les images n’ont pas de dépendances directes entre elles. Pour exécuter toutes les cibles d’un groupe, il suffit d’utiliser la commande suivante :
Cette commande va automatiquement repérer les cibles définies dans le fichier Bake et les exécuter en fonction de la configuration. Si vous souhaitez exécuter une cible spécifique, vous pouvez la préciser comme ceci :
Docker Bake vous offre ainsi une grande flexibilité pour organiser et orchestrer des processus de build complexes en fonction des besoins spécifiques de votre projet.
Définition des groups
Les groupes vous permettent d’organiser plusieurs cibles en un seul ensemble. Cela permet d’exécuter plusieurs builds en parallèle ou de séquencer des builds en fonction des besoins du projet.
Héritage
Docker Bake supporte le concept d’héritage, permettant à une cible de build d’hériter des propriétés d’une ou plusieurs autres cibles. Ce mécanisme simplifie la gestion des configurations complexes en réutilisant et en étendant des blocs de construction existants. Par exemple, vous pouvez définir une cible parent avec des configurations communes, puis créer des cibles enfants qui héritent de ces propriétés tout en ajoutant ou en modifiant certains paramètres.
Exemple d’héritage :
Dans cet exemple, les cibles frontend
et backend
héritent toutes deux des
propriétés de la cible base
, ce qui permet de partager des configurations
communes comme le contexte et certaines parties du Dockerfile. Cela réduit la
duplication de code et rend les fichiers de configuration plus faciles à
maintenir.
L’héritage est particulièrement utile dans des projets où plusieurs cibles partagent une grande partie de la même configuration, mais nécessitent des ajustements spécifiques. Il permet de centraliser les configurations communes tout en offrant la flexibilité nécessaire pour adapter chaque build aux besoins spécifiques du service ou de l’application.
Utilisation des variables
Docker Bake permet d’utiliser des variables pour rendre vos fichiers de
configuration plus dynamiques et réutilisables. Les variables peuvent être
définies dans le fichier de configuration Bake, passées via la ligne de
commande, ou provenant de fichiers .env
. Cela permet d’ajuster les builds en
fonction de différents environnements ou configurations sans modifier
directement le fichier Bake.
Exemple de fichier avec variables
Ici, la variable version
est utilisée pour générer dynamiquement le tag de
l’image.
Les variables peuvent être déclarées avec une valeur par défaut et peuvent être surchargées en ligne de commande :
Expressions
Docker Bake prend en charge l’évaluation des expressions dans les fichiers HCL, ce qui permet d’effectuer des opérations arithmétiques, de définir des valeurs conditionnellement et plus encore.
Opérations arithmétiques
Vous pouvez réaliser des calculs directement dans vos configurations. Par exemple, pour multiplier deux nombres :
En imprimant le fichier avec --print
, Docker Bake évalue et affiche la valeur
calculée :
Opérateurs ternaires
Les opérateurs ternaires permettent de conditionner l’attribution de valeurs. Par exemple, ajouter un tag seulement si une variable n’est pas vide :
Si TAG
est vide, seul le tag my-image:latest
est appliqué.
Expressions avec des variables
Les expressions peuvent être combinées avec des variables pour conditionner les arguments de build ou effectuer des calculs. Par exemple :
Fonctions intégrées
Docker Bake propose une série de fonctions intégrées pour manipuler les données dans vos fichiers de configuration. Ces fonctions permettent d’effectuer des opérations comme la manipulation de chaînes, l’évaluation conditionnelle, et la gestion de listes. Par exemple, vous pouvez utiliser des fonctions pour concaténer des chaînes, transformer des variables, ou effectuer des conversions dynamiques.
Exemple de fonction :
Ici, la fonction upper
transforme var.name
en majuscules et replace
substitue les points dans var.version
par des underscores.
Docker Bake prend en charge plusieurs fonctions intégrées qui permettent de manipuler les chaînes de caractères, effectuer des opérations conditionnelles, et gérer des listes dans vos fichiers de configuration. Parmi les fonctions disponibles, on trouve :
upper
etlower
: convertissent une chaîne de caractères en majuscules ou minuscules.replace
: remplace une sous-chaîne par une autre.contains
: vérifie si une chaîne ou une liste contient un élément donné.notequal
: compare deux valeurs et retourne vrai si elles ne sont pas égales.join
: combine les éléments d’une liste en une seule chaîne.
Pour une liste complète et des exemples, consultez la documentation officielle ↗.
Matrices de build
Docker Bake permet de définir des matrices de build, ce qui vous permet de construire plusieurs variantes d’une image Docker en une seule commande. Les matrices combinent plusieurs variables pour générer différentes configurations de build, comme des versions spécifiques de l’application ou des architectures cibles.
Exemple de matrice :
Cela construit les images pour chaque combinaison d’environnement et de plateforme.
Gestion des contextes
Docker Bake permet de spécifier des contextes de build pour définir les sources de vos builds, qu’il s’agisse de répertoires locaux, de référentiels Git, ou de fichiers tar. Un contexte de build fournit les fichiers et dossiers nécessaires pour construire l’image Docker. Vous pouvez également utiliser plusieurs contextes dans un même fichier Bake, permettant une flexibilité accrue dans la gestion des sources de vos builds.
Mise en oeuvre
Dans ce tutoriel, nous allons créer un projet simple en utilisant Docker Bake avec un fichier HCL. Nous allons enrichir ce fichier progressivement tout en utilisant des concepts comme les cibles, les variables, les expressions, l’héritage, les contextes, les matrices de build.
Structure du projet
Voici la structure de notre projet :
- docker-bake.hcl
Répertoirefrontend/
- Dockerfile
- index.js
Répertoirebackend/
- Dockerfile
- app.py
- requirements.txt
Les fichiers
Pour le frontend
Pour le backend
Étapes de la configuration Docker Bake
Dans un premier temps, nous allons créer les deux target
pour le backend et le
frontend :
On créé le groupe default
contenant les deux targets backend
et frontend
.
Validons le contenu du fichier avec la commande suivante :
Étape 2 : Ajout de variables pour la flexibilité
En bon DevOps, nous n’utilisons pas les tags latest
. Remplaçons-les par des
versions dans des variables
On relance la commande de check :
On voit que les tags ont pris les bonnes valeurs. Tentons de construire nos images :
Le build s’est bien passé en parallèle. On vérifie les images :
Définissons-le comme builder par défaut :
Ajouter dans les targets les plateformes cibles :
Lançons le build :
On retrouve nos deux fichiers tar.gz
dans le dossier où la commande a été
lançé.
Ce petit tutoriel montre comment structurer un projet Docker avec Docker Bake, permettant des builds flexibles et optimisés pour différents environnements et plateformes.
Pour approfondir, consultez la documentation Docker Bake ↗.
Conclusion
En utilisant Docker Bake, nous avons pu orchestrer de manière efficace les builds d’une application multi-service composée d’un frontend Node.js et d’un backend Flask. Grâce à la simplicité et à la flexibilité offertes par Docker Bake, nous avons pu gérer les configurations, optimiser les builds, et centraliser la gestion des services dans un fichier unique. Cet outil s’avère indispensable pour les projets nécessitant des builds complexes et des déploiements automatisés, tout en conservant une approche déclarative et cohérente.
Docker Bake facilite ainsi le workflow DevOps, permettant de se concentrer davantage sur le développement et l’optimisation des applications, tout en simplifiant la gestion des builds et des déploiements. Avec une configuration bien pensée, vous pouvez aisément gérer les besoins de votre projet, qu’il s’agisse de services simples ou d’environnements complexes à plusieurs composants.
Pour aller plus loin et explorer d’autres cas d’utilisation de Docker Bake, vous pouvez consulter la documentation officielle de Docker Bake ↗.