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.
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).
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 :
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 :
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.
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 :
FROM alpine:3.18
RUN echo "hello" > /tmp/hello.txt
Construisez-le avec BuildKit :
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 :
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 :
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 :
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
- Variables d'environnement :
DOCKER_BUILDKIT=1pour forcer BuildKit (pour les anciens clients Docker). - Fichier de configuration du démon :
/etc/docker/daemon.json(Linux) ou les paramètres de Docker Desktop (Mac/Windows). - 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 :
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 :
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 :
{
"debug": true,
"features": {
"buildkit": true
}
}
Redémarrez ensuite Docker :
sudo systemctl restart docker
Vérifiez que le démon a redémarré sans erreur :
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
FROM alpine
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
Passez le secret au moment du build :
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 :
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 :
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 :
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 :
sudo journalctl -u docker -f
Pour un pilote de conteneur buildx, trouvez le nom du conteneur et affichez les journaux :
docker ps -a --filter "name=buildx_buildkit"
# notez l'ID du conteneur, puis :
docker logs <container-id> --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 :
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.
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 :
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 :
- Vérifiez l'environnement :
echo $DOCKER_BUILDKIT(devrait être vide ou1). - Désactivez-la si elle est
0:unset DOCKER_BUILDKIT. - Ou forcez BuildKit :
DOCKER_BUILDKIT=1 docker build -t myapp .. - 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 :
- Vérifiez la taille du contexte de build :
docker build --progress=plain -t myapp . 2>&1 | grep "transferred" - Utilisez
.dockerignorepour exclure les fichiers inutiles. Créez un fichier.dockerignoreavec des motifs comme :
.git
*.log
node_modules
- Si l'erreur persiste, essayez de vider le cache de build :
docker builder prune -f. - 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 :
- Installez ou mettez à jour buildx : suivez la documentation Docker pour votre système d'exploitation.
- Alternativement, utilisez BuildKit intégré sans buildx en définissant
DOCKER_BUILDKIT=1et en utilisantdocker build(pasdocker 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 :
- Vérifiez l'utilisation du disque :
df -h /var/lib/docker/buildkit(oudocker system df). - Élaguez le cache BuildKit :
docker builder prune -a -f(attention : supprime tout le cache de build). - 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. - 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 :
- Connectez-vous au registre :
docker login <registry>. - Vérifiez que vous pouvez extraire l'image manuellement :
docker pull <image>. - 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
--pushavecdocker buildx buildet le bon--secretpour l'authentification du registre si nécessaire. - 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 <image> 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 :
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é :
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.