## Introduction Docker BuildKit est le moteur de construction moderne pour les images Docker, offrant des builds plus rapides, une meilleure mise en cache et des fonctionnalités avancées comme les secrets et l'exécution parallèle des étapes. Mais lorsqu'un build échoue avec une erreur cryptique, la puissance de BuildKit peut rendre le dépannage plus complexe que l'ancien constructeur. Ce guide fournit des étapes pratiques, axées sur les commandes, pour diagnostiquer et corriger les problèmes courants de BuildKit, du cache de build manquant aux erreurs de configuration. Nous nous concentrerons sur la sécurité opérationnelle : observer l'état actuel avant d'apporter des modifications, limiter le rayon d'impact de toute modification, utiliser des espaces réservés pour les secrets, vérifier chaque correction et documenter les étapes de récupération. L'article s'adresse aux développeurs, ingénieurs DevOps et équipes techniques de startups qui utilisent Docker en production ou dans les pipelines CI. Vous apprendrez à inspecter la version et l'environnement de BuildKit, consulter les journaux, interpréter le comportement du cache, ajuster la configuration en toute sécurité et récupérer des modes de défaillance fréquents. Chaque section comprend des commandes concrètes, des sorties attendues et des décisions de récupération. ## Inventaire de la version et de l'environnement Avant de plonger dans des erreurs spécifiques, établissez une base de référence. Connaître la version exacte de BuildKit et la configuration de Docker vous aidera à éviter de poursuivre des problèmes déjà corrigés dans une version ultérieure ou causés par des différences d'environnement. ### Vérifier la version de Docker et de BuildKit Exécutez `docker version` pour voir les versions du client et du serveur. BuildKit est intégré au démon Docker, mais sa version peut différer selon la version de Docker. ```bash docker version --format '{{.Server.Version}}' ``` Exemple de sortie : ``` 24.0.5 ``` Pour vérifier spécifiquement la version de BuildKit, utilisez `docker buildx version` si vous avez le plugin buildx (souvent inclus). ```bash docker buildx version ``` Exemple de sortie : ``` github.com/docker/buildx v0.11.2 9872040 ``` ### Vérifier que BuildKit est activé BuildKit est le constructeur par défaut pour Docker 23.0 et versions ultérieures. Vous pouvez le confirmer en exécutant un build simple et en regardant le format de sortie de BuildKit. Ou vérifiez la configuration du démon : ```bash docker info --format '{{.Builder}}' ``` Si la sortie est `buildkit`, il est actif. Si elle indique `legacy`, vous devez activer BuildKit. ### Comprendre l'environnement de build BuildKit peut s'exécuter dans différents contextes : le démon Docker par défaut, un conteneur Docker (par exemple, le pilote `docker-container`) ou un pod Kubernetes. Listez vos constructeurs : ```bash docker buildx ls ``` Exemple : ``` NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS default * docker default default running linux/amd64, linux/arm64 ``` Connaître le pilote est important car certaines fonctionnalités comme les builds multi-plateformes ne fonctionnent qu'avec le pilote `docker-container`. ### Inspecter les ressources de build actuelles Vérifiez les conteneurs, réseaux ou volumes de build existants qui pourraient entrer en conflit. ```bash docker ps -a --filter "name=buildx_buildkit" ``` Si vous voyez un conteneur BuildKit arrêté, il peut être nécessaire de le redémarrer ou de le nettoyer. ### Test pratique de type production Avant de déboguer un pipeline complexe, reproduisez le problème dans un projet local minimal. Créez un Dockerfile simple : ```dockerfile FROM alpine:3.18 RUN echo "hello" > /tmp/hello.txt ``` Construisez-le avec BuildKit : ```bash docker build -t test-buildkit . ``` Si cela réussit, mais que votre build réel échoue, le problème se situe probablement dans les instructions de votre Dockerfile ou le contexte de build, pas dans BuildKit lui-même. Pour confirmer que les fichiers sont persistés correctement, exécutez un conteneur à partir de l'image et vérifiez le système de fichiers : ```bash docker run --rm test-buildkit cat /tmp/hello.txt ``` Sortie attendue : ``` hello ``` Testez ensuite le comportement de redémarrage en exécutant le conteneur avec un volume nommé et en écrivant des données : ```bash docker run -d --name data-test -v app_data:/data alpine sh -c "echo persistent > /data/file.txt && sleep 300" docker exec data-test cat /data/file.txt ``` Sortie : ``` persistent ``` Arrêtez et supprimez maintenant le conteneur, puis exécutez-en un nouveau avec le même volume : ```bash docker rm -f data-test docker run --rm -v app_data:/data alpine cat /data/file.txt ``` Si la sortie est toujours `persistent`, votre configuration de volume est correcte. Sinon, les données ont été écrites dans la couche du conteneur au lieu du volume. ## Chemin de configuration sûr La configuration de BuildKit peut provenir de variables d'environnement, de paramètres du démon ou d'options du constructeur buildx. Modifier incorrectement la configuration peut casser tous les builds, suivez donc une approche systématique : observez, sauvegardez, modifiez un élément, testez et revenez en arrière si nécessaire. ### Emplacements de configuration clés 1. **Variables d'environnement** : `DOCKER_BUILDKIT=1` pour forcer BuildKit (pour les anciens clients Docker). 2. **Fichier de configuration du démon** : `/etc/docker/daemon.json` (Linux) ou les paramètres de Docker Desktop (Mac/Windows). 3. **Configuration du constructeur buildx** : stockée dans `~/.docker/buildx/` ou dans le conteneur du constructeur. ### Procédure de modification sûre Avant d'apporter des modifications, capturez la configuration actuelle : ```bash docker buildx inspect --bootstrap ``` Exemple de sortie (tronquée) : ``` Name: default Driver: docker Nodes: Name: default Endpoint: default Status: running Buildkit: v0.12.4 ``` Enregistrez la sortie dans un fichier pour référence de retour en arrière. Sauvegardez également le daemon.json s'il existe : ```bash sudo cp /etc/docker/daemon.json /etc/docker/daemon.json.backup ``` Lorsque vous modifiez un paramètre, redémarrez Docker et vérifiez que le changement a pris effet. Par exemple, pour activer la journalisation verbeuse de BuildKit, ajoutez ce qui suit à `daemon.json` : ```json { "debug": true, "features": { "buildkit": true } } ``` Redémarrez ensuite Docker : ```bash sudo systemctl restart docker ``` Vérifiez que le démon a redémarré sans erreur : ```bash sudo journalctl -u docker -n 50 --no-pager ``` Recherchez des lignes comme `level=info msg="Daemon has completed initialization"`. ### Gestion des secrets et des données sensibles Ne codez jamais en dur des secrets dans les Dockerfiles ou les arguments de build. Utilisez les secrets BuildKit : ```dockerfile # Dockerfile FROM alpine RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret ``` Passez le secret au moment du build : ```bash docker build --secret id=mysecret,src=./secret.txt -t myapp . ``` Si vous exposez accidentellement un secret, révoquez-le immédiatement et faites pivoter les informations d'identification. Utilisez `docker history` pour voir si des secrets ont été intégrés dans une image : ```bash docker history --no-trunc myapp ``` Si vous voyez la valeur du secret, reconstruisez et poussez une nouvelle image ; n'utilisez pas celle qui est compromise. ## Vérification et diagnostics Lorsqu'un build échoue, la première étape consiste à rassembler les journaux et à comprendre l'erreur. BuildKit fournit une sortie détaillée, mais parfois vous devez augmenter la verbosité ou inspecter l'état interne. ### Activer les journaux de build détaillés Par défaut, `docker build` affiche la progression et les erreurs. Pour voir plus de détails, utilisez `--progress=plain` : ```bash docker build --progress=plain -t myapp . ``` Cela imprime la sortie de chaque étape sans les barres de progression fantaisistes, ce qui est utile pour lire les erreurs. Pour encore plus de détails, définissez le niveau de journalisation de BuildKit via une variable d'environnement avant d'exécuter le build : ```bash export BUILDKIT_PROGRESS=plain docker build -t myapp . ``` Ou exécutez le démon avec une journalisation de débogage (comme décrit dans la section précédente). ### Examiner les journaux du démon BuildKit Si le démon de build lui-même plante ou se comporte de manière inattendue, inspectez ses journaux. Pour le démon Docker par défaut : ```bash sudo journalctl -u docker -f ``` Pour un pilote de conteneur buildx, trouvez le nom du conteneur et affichez les journaux : ```bash docker ps -a --filter "name=buildx_buildkit" # notez l'ID du conteneur, puis : docker logs --tail 100 ``` ### Diagnostiquer les échecs de cache Une frustration courante est que les builds n'utilisent pas le cache. Pour voir ce qui a causé un échec de cache, exécutez avec `--progress=plain` et cherchez des lignes comme `CACHED` ou `RUN` sans cache. Par exemple : ``` #7 [stage-0 2/4] RUN apt-get update && apt-get install -y curl #7 0.523 + apt-get update #7 1.234 ... #7 DONE 12.3s ``` Si une étape n'est pas `CACHED`, quelque chose a changé dans les couches précédentes ou la commande elle-même. Utilisez `docker buildx du` pour vérifier l'utilisation du cache : ```bash docker buildx du ``` Exemple : ``` Total: 123.4MB ``` Si le cache est trop petit, vous devrez peut-être augmenter la taille du cache dans la configuration du constructeur. ### Débogage interactif Vous pouvez exécuter un conteneur avec le même système de fichiers qu'une étape de build échouée. Utilisez `docker buildx debug` si disponible, ou répliquez manuellement les instructions du Dockerfile dans une image de base. ```bash docker run -it --rm alpine:3.18 sh ``` Dans le conteneur, exécutez la commande défaillante pour voir l'erreur de manière interactive. ### Vérification de l'état de BuildKit Vérifiez que BuildKit fonctionne en vérifiant le point de terminaison de l'API BuildKit (s'il est exposé). Pour un pilote de conteneur, trouvez le port : ```bash docker port buildx_buildkit_default ``` Exemple : ``` 1234/tcp -> 0.0.0.0:1234 ``` Utilisez ensuite `docker buildx inspect --bootstrap` pour vous assurer que le constructeur est en cours d'exécution. ## Modes de défaillance et récupération Cette section couvre les échecs BuildKit les plus fréquents, leurs symptômes et la récupération étape par étape. ### Échec 1 : « BuildKit est activé mais le client de build ne l'utilise pas » **Symptôme** : Vous voyez une sortie qui ressemble à l'ancien constructeur (par exemple, `Sending build context to Docker daemon`) même si la version de Docker est 23+. **Cause** : La variable d'environnement `DOCKER_BUILDKIT` peut être définie sur `0`, ou le client est ancien. **Récupération** : 1. Vérifiez l'environnement : `echo $DOCKER_BUILDKIT` (devrait être vide ou `1`). 2. Désactivez-la si elle est `0` : `unset DOCKER_BUILDKIT`. 3. Ou forcez BuildKit : `DOCKER_BUILDKIT=1 docker build -t myapp .`. 4. Mettez à niveau Docker si la version est inférieure à 23.0. ### Échec 2 : « failed to solve: rpc error: code = Unknown desc = failed to compute cache key » **Symptôme** : Le build échoue avec une erreur de clé de cache, souvent lors de la copie de fichiers. **Cause** : Le contexte de build est trop volumineux, ou il y a un fichier qui change fréquemment (comme un fichier journal) qui invalide le cache, ou il y a des problèmes de permissions. **Récupération** : 1. Vérifiez la taille du contexte de build : `docker build --progress=plain -t myapp . 2>&1 | grep "transferred"` 2. Utilisez `.dockerignore` pour exclure les fichiers inutiles. Créez un fichier `.dockerignore` avec des motifs comme : ``` .git *.log node_modules ``` 3. Si l'erreur persiste, essayez de vider le cache de build : `docker builder prune -f`. 4. Reconstruisez. ### Échec 3 : « BuildKit non pris en charge par le démon » **Symptôme** : Message d'erreur : `ERROR: BuildKit is enabled but the buildx component is missing or broken`. **Cause** : Le plugin buildx n'est pas installé ou est obsolète. **Récupération** : 1. Installez ou mettez à jour buildx : suivez la documentation Docker pour votre système d'exploitation. 2. Alternativement, utilisez BuildKit intégré sans buildx en définissant `DOCKER_BUILDKIT=1` et en utilisant `docker build` (pas `docker buildx build`). ### Échec 4 : « no space left on device » pendant le build **Symptôme** : Le build échoue avec « no space left on device », même si le disque a de l'espace libre. **Cause** : BuildKit utilise une zone de stockage séparée (souvent dans `/var/lib/docker/buildkit` ou le conteneur du constructeur) qui peut être pleine en raison de la croissance du cache. **Récupération** : 1. Vérifiez l'utilisation du disque : `df -h /var/lib/docker/buildkit` (ou `docker system df`). 2. Élaguez le cache BuildKit : `docker builder prune -a -f` (attention : supprime tout le cache de build). 3. Si vous utilisez un pilote de conteneur, augmentez la taille du volume ou élaguez le conteneur : `docker rm -f buildx_buildkit_default && docker buildx create --use`. 4. Reconstruisez. ### Échec 5 : « failed to load cache key: pull access denied » **Symptôme** : Le build échoue lors de la tentative d'extraction d'une image de base ou d'un cache à partir d'un registre, avec un accès refusé. **Cause** : Problème d'authentification ou permissions manquantes dans le registre. **Récupération** : 1. Connectez-vous au registre : `docker login `. 2. Vérifiez que vous pouvez extraire l'image manuellement : `docker pull `. 3. Si vous utilisez un pilote de conteneur buildx, assurez-vous que le conteneur du constructeur a accès aux informations d'identification. Utilisez le drapeau `--push` avec `docker buildx build` et le bon `--secret` pour l'authentification du registre si nécessaire. 4. Vérifiez vos permissions de registre. ## Liste de contrôle des opérations Utilisez cette liste de contrôle avant et après toute session de dépannage BuildKit pour vous assurer de couvrir les étapes essentielles et de minimiser les risques. | # | Étape | Commande / Action | Résultat attendu | Responsable | Fréquence de révision | |---|------|------------------|-----------------|-------|----------------| | 1 | Vérifier que BuildKit est activé | `docker info --format '{{.Builder}}'` | `buildkit` | Responsable DevOps (Priya Shah) | Mensuel | | 2 | Vérifier la version | `docker buildx version` | Dernière version stable | Responsable DevOps | Mensuel | | 3 | Inspecter l'état du constructeur | `docker buildx ls` | Tous les constructeurs en cours d'exécution | Responsable DevOps | Hebdomadaire | | 4 | Tester un build minimal | `docker build -t test-buildkit .` avec un Dockerfile simple | Le build réussit | Développeur de garde (Alex Chen) | À chaque déploiement | | 5 | Examiner la taille du cache de build | `docker buildx du` | Utilisation inférieure à 80 % de l'espace alloué | Responsable DevOps | Hebdomadaire | | 6 | Vérifier les builds échoués | `docker ps -a --filter "status=exited" --filter "name=buildx"` | Aucun conteneur de build inattendu arrêté | Développeur de garde | Quotidien | | 7 | Sauvegarder la configuration | `cp /etc/docker/daemon.json /etc/docker/daemon.json.backup` | Le fichier de sauvegarde existe | Responsable DevOps | Avant tout changement de configuration | | 8 | Valider la gestion des secrets | S'assurer qu'il n'y a pas de secrets dans `docker history` | Historique propre | Agent de sécurité (Jordan Lee) | Trimestriel | **Responsable et fréquence de révision** Chaque élément de la liste de contrôle a un seul responsable pour éviter toute ambiguïté. Par exemple, le Responsable DevOps est responsable de l'intégrité de la configuration et la révise mensuellement ou avant tout changement. Le Développeur de garde gère les échecs de build et révise quotidiennement. L'Agent de sécurité audite la gestion des secrets trimestriellement. Ces révisions doivent être documentées dans votre système de gestion des incidents. ## Pièges courants et comment les éviter Même les utilisateurs Docker expérimentés rencontrent des pièges BuildKit. Voici les plus fréquents et les mesures préventives. ### Piège 1 : Ignorer `.dockerignore` **Pourquoi cela arrive** : Les développeurs oublient souvent de créer ou de mettre à jour `.dockerignore`, ce qui entraîne des contextes de build énormes et une invalidation du cache. **Comment éviter** : Incluez toujours un `.dockerignore` à la racine du projet. Commencez par des motifs pour VCS, journaux et dépendances : ``` .git .gitignore *.log node_modules target/ ``` **Récupération** : Si un build est lent ou que les échecs de cache sont constants, vérifiez la taille du contexte de build avec `docker build --progress=plain . | grep "transferred"`. Ajoutez les motifs manquants à `.dockerignore` et reconstruisez. ### Piège 2 : Utiliser à mauvais escient les arguments de build pour les secrets **Pourquoi cela arrive** : Passer des secrets via `ARG` ou `ENV` est pratique mais les laisse dans les couches de l'image. **Comment éviter** : Utilisez les secrets BuildKit (`RUN --mount=type=secret`) pour les données sensibles pendant le build. N'intégrez jamais de secrets dans l'image finale. **Récupération** : Si vous soupçonnez que des secrets ont été intégrés, exécutez `docker history --no-trunc ` et recherchez le secret. S'il est trouvé, révoquez le secret et reconstruisez sans lui, puis poussez une image propre. ### Piège 3 : Élaguer le cache de manière trop agressive **Pourquoi cela arrive** : Pour tenter de résoudre des problèmes, les utilisateurs exécutent `docker builder prune -a -f` sans considérer l'impact. **Comment éviter** : Utilisez un élagage ciblé : `docker builder prune --filter "until=24h"` pour supprimer uniquement l'ancien cache. Ou utilisez `docker buildx prune --keep-storage=10GB` pour limiter l'élagage. **Récupération** : Si vous perdez du cache inutilement, la reconstruction prendra plus de temps. Pour éviter un élagage excessif à l'avenir, documentez les politiques de gestion du cache et utilisez des filtres. ### Piège 4 : Exécuter BuildKit dans des environnements non pris en charge **Pourquoi cela arrive** : Essayer d'utiliser des fonctionnalités BuildKit (comme les builds multi-plateformes) avec le pilote Docker par défaut, qui ne les prend pas en charge. **Comment éviter** : Vérifiez les capacités du pilote avec `docker buildx ls`. Si vous avez besoin de fonctionnalités avancées, créez un nouveau constructeur avec le pilote `docker-container` : ```bash docker buildx create --name mybuilder --driver docker-container --use docker buildx inspect --bootstrap ``` **Récupération** : Passez au constructeur approprié en utilisant `docker buildx use mybuilder`. ### Piège 5 : Ne pas surveiller l'utilisation des ressources de BuildKit **Pourquoi cela arrive** : Les conteneurs BuildKit peuvent consommer beaucoup de CPU et de mémoire, surtout lors de builds parallèles, entraînant l'épuisement des ressources de l'hôte. **Comment éviter** : Définissez des limites de ressources pour le conteneur du constructeur lors de la création d'un constructeur personnalisé : ```bash docker buildx create --driver docker-container --driver-opt env.BUILDKIT_STEP_LOG_MAX_SIZE=10m --driver-opt env.BUILDKIT_STEP_LOG_MAX_SPEED=1m mybuilder ``` Surveillez également avec `docker stats buildx_buildkit_mybuilder`. **Récupération** : Si le constructeur ne répond pas, redémarrez-le : `docker restart buildx_buildkit_mybuilder`. ## Conclusion Le dépannage de Docker BuildKit nécessite une approche méthodique : commencez par les vérifications de version et d'environnement, inspectez les journaux, ajustez la configuration en toute sécurité et récupérez des modes de défaillance connus. Les exemples pratiques de ce guide devraient vous aider à résoudre rapidement la plupart des problèmes de build. N'oubliez pas de toujours observer l'état actuel, d'apporter une modification à la fois, de vérifier le résultat et de documenter le processus de récupération. Les fonctionnalités avancées de BuildKit peuvent améliorer considérablement les performances de build, mais elles introduisent également de nouvelles complexités. En suivant les listes de contrôle et en évitant les pièges courants, vous pouvez garder vos builds fiables et votre équipe productive. Pour une prochaine étape, choisissez une vérification à faible risque dans la liste de contrôle des opérations, comme tester un build minimal ou examiner l'utilisation du cache. Enregistrez l'état actuel, exécutez la commande, comparez le résultat avec la sortie attendue, puis étudiez toute divergence. Avec la pratique, vous développerez un sens intuitif du comportement de BuildKit et serez capable de résoudre n'importe quel échec de build en toute confiance.