Maitriser BuildX
Mise à jour :
Introduction
Depuis la version 23.0 de
Docker, BuildKit
est devenu le
moteur de création d’images de conteneurs par défaut en remplacement de l’ancien
qui devenait obsolète face à ses concurrents que sont Buildah
,
Kaniko
par exemple.
Aujourd’hui, je vais parler de certaines nouvelles fonctionnalités qui
permettent d’utiliser différents contextes de construction d’images.
Petit tour des fonctionnalités de Buildkit
BuildKit est pour moi une petite révolution dans le domaine des outils de constructions d’image que j’ai manquée. Je m’étais amusé à l’utiliser pour générer des images en parallèle une image à destination de plusieurs plateformes, mais sans en saisir tout le potentiel des nouvelles fonctionnalités qu’il intégrait.
En fait BuildKit est un produit à part entière. Il possède une architecture
permettant de supporter d’autres langages de définition d’images, autre que les
Dockerfile
, mais aussi plusieurs formats de sortie des images. Il peut être
utilisé via Docker Desktop ou Docker
Engine, déployé sur des machines
distantes, mais aussi des clusters Kubernetes.
Pour améliorer les temps de constructions, il fait appel à un DAG qui permet :
- De paralléliser la construction des étapes indépendantes.
- De détecter et de bypasser des étapes inutiles
- D’améliorer la copie des fichiers depuis le contexte local
- D’utiliser des caches dans des volumes
L’intégration de Buildkit dans Docker Engine
Le sujet est complexe à expliquer, car la documentation est difficile à comprendre. Elle est éclatée un peu partout et pas forcément à jour.
Il faut bien comprendre que BuildKit est un moteur de construction d’images
qui est intégré dans Docker Engine
et Docker Desktop
. L’intégration dans
Docker Engine
se fait via le plugin buildx
qui normalement est installé
avec. Vérifions :
Le plugin Buildx
est défini par défaut, mais pourrait être remplacé par un
autre.
Buildx
est très souple, car il permet d’utiliser différents drivers. Chaque
pilote définit comment et où la construction de l’image se fait et possède ses
propres fonctionnalités.
Parmi les drivers actuellement supportés, on trouve les suivants :
- Le driver
docker
le driver par défaut qui utilise Docker installé localement. - Le driver
docker-container
qui permet la création d’un environnement BuildKit personnalisable dans un conteneur Docker. - Le driver
kubernetes
qui permet de lancer des constructions sur des clusters kubernetes. - Le driver
remote
qui permet de lancer des constructions sur des machines distantes ou BuildKit est installé en tant que démon.
On voit que tout est pensé pour le rendre très souple et pour pouvoir déporter
les constructions d’images de containers un peu partout. Dans ce billet, je vais
me limiter à l’utiliser aux drivers docker
et docker-container
, mais je
prévois d’écrire des billets sur les deux autres drivers.
Le driver docker
Le driver Docker
ne possède pas de paramètres pour le moment. C’est celui qui
est invoqué avec la commande docker build
. Il ne permet pas par exemple de
construire d’images pour d’autres plateformes.
Le driver docker-container
Le driver docker-container
possède les paramètres suivants :
image=<IMAGE>
qui permet de définir l’image du conteneur à utiliser pour exécuter BuildKit.network=<NETMODE>
qui permet de définir le mode réseau pour exécuter le conteneur BuildKit.cgroup-parent=<CGROUP>
qui permet de définir lecgroup
parent du conteneur BuildKit si docker utilise le pilotecgroupfs
. La valeur par défaut est/docker/buildx
.
Dans ce billet, nous n’utiliserons aucune de ces options.
Gestion des instances
Les instances de constructeur sont des environnements isolés dans lesquels des builds peuvent être lancés.
Lister les instances
Pour obtenir la liste des instances disponibles, on utilise la commande ls
:
On ne retrouve que celui du driver docker
par défaut.
Inspection d’une instance
Pour obtenir la liste complète des paramètres actuels, on fait appel à la
commande inspect
.
Création d’une instance
La commande create
permet de créer de nouvelles instances de constructeur.
Voyons comment créer une nouvelle instance utilisant le driver
docker-container
.
L’option --bootstrap
permet de démarrer l’instance après sa création.
Faisons quelques vérifications :
On retrouve une image de BuildKit fournie par le projet moby sur lequel
tourne le démon buildkitd
.
Construction d’une image utilisant le driver docker-container
On prend un simple Dockerfile
:
Lors du build, il faut indiquer la sortie, car lors de la création de l’instance, elle n’a pas été indiqué. On a à notre disposition deux options :
--load
pour la charger dans Docker--push
pour la pousser directement dans une registry
On utilisera ici l’option --load
:
Notre image a bien été créé !
Le multi-plateforme
Nous allons créer une seconde instance prenant en charge des plateformes autres celles de l’hôte.
Vérifions que nous avons bien notre nouvelle instance :
On voit bien que nos plateformes s’ajoutent à celle de notre hôte.
On tente le build en indiquant la plateforme arm/v8
:
On inspecte l’image :
On a bien une image pour les processeurs arm/v8
. Cela simplifie énormément le
process à mon précédent test.
Définition de l’instance par défaut
La commande use
permet de définir l’instance à utiliser par défaut.
Lors de la création d’une instance, il est possible d’utiliser le paramètre
--use
pour basculer directement sur celui-ci.
Arrêt d’une instance
L’arrêt d’une instance se fait avec la commande stop
:
Vérifions le resultat :
Il n’y a pas de commande start car il suffit de relancer un build pour que l’instance démarre.
Destruction des instances
La commande rm
permet de détruire une instance de construction.
Faire du ménage
Buuildkit
utilise des ressources et il faut pouvoir faire de temps en temps un
peu le ménage. Pour cela, nous avons deux commandes : du
pour obtenir des
informations sur l’espace disque occupé et prune
pour le nettoyage.
Dans mon test vu que mon image est des plus simples cela ne change rien. Mais si on construit des images plus complexes alors là cela change tout.
Conclusion
En conclusion, BuildKit offre aux administrateurs systèmes et aux développeurs une solution plus rapide, plus sûre et plus efficace pour la construction d’images Docker. Grâce à ses fonctionnalités avancées telles que la mise en cache, la parallélisation des builds et la gestion optimisée des dépendances, BuildKit permet non seulement d’économiser du temps et des ressources, mais contribue également à renforcer la sécurité des images Docker.
L’intégration de BuildKit dans vos workflows DevOps peut significativement améliorer la vitesse de développement et de déploiement, tout en assurant la conformité aux normes de sécurité. Avec les bonnes pratiques et une configuration appropriée, BuildKit ouvre la porte à des builds plus robustes et à une meilleure gestion des containers.
Je vous encourage vivement à adopter BuildKit dans vos projets, à expérimenter avec ses fonctionnalités avancées et à partager vos propres expériences et astuces avec la communauté. Ensemble, continuons à pousser les limites de l’efficacité et de la sécurité dans le développement de logiciels.