Introduction
Le cache de construction de Docker est l'une des fonctionnalités les plus puissantes pour accélérer la création d'images, mais c'est aussi l'une des plus mal comprises en environnement de production. Lorsque le cache fonctionne, les builds sont rapides et prévisibles. Lorsqu'il ne fonctionne pas, les développeurs perdent du temps à déboguer des builds incohérents et les opérateurs peuvent déployer des images plus volumineuses ou plus anciennes que prévu. Cet article fournit une liste de contrôle opérationnelle en production pour le cache de construction Docker, avec des exemples pratiques qui vous mènent d'un problème observé à un résultat vérifié.
Nous couvrirons les éléments essentiels : identifier la version de Docker et de BuildKit installée, comprendre votre topologie de déploiement, vérifier les prérequis et inspecter le composant exact qui se comporte mal. L'objectif est la sécurité opérationnelle : observer avant de changer, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets, vérifier le résultat et documenter comment récupérer si l'état attendu n'est pas atteint.
Ce guide est destiné aux développeurs, consultants DevOps et équipes techniques de startups qui gèrent Docker en production. Il relie les opérations de cache de construction Docker, les éléments de liste de contrôle, les bonnes pratiques et la maintenance à des commandes réelles, des sorties attendues, des signaux d'échec et des décisions de récupération.
Inventaire des versions et de l'environnement
Avant de toucher au cache, vous devez savoir avec quoi vous travaillez. L'inventaire des versions et de l'environnement répond : quelle version de Docker, quelle version de BuildKit, quel pilote de stockage et quel contexte de build utilisez-vous ? Ces détails affectent considérablement le comportement du cache.
Vérifier les versions de Docker et BuildKit
docker version
La sortie attendue comprend des sections distinctes pour le client et le serveur. Recherchez les lignes OS/Arch, Version et Git commit. Pour BuildKit, vérifiez s'il est activé :
docker buildx version
Si BuildKit est activé, vous verrez buildx dans la sortie. BuildKit est le constructeur par défaut sur Docker Desktop et sur de nombreuses distributions Linux avec Docker 23.0+. Pour confirmer que BuildKit est utilisé pour les builds :
docker buildx ls
Si vous voyez un constructeur nommé default avec BuildKit dans la colonne driver, vous utilisez BuildKit. Si vous voyez docker comme driver, vous utilisez le constructeur hérité. BuildKit a une sémantique de cache différente et est requis pour les fonctionnalités de cache avancées comme --mount=type=cache.
Comprendre le pilote de stockage
docker info --format '{{.Driver}}'
Les pilotes courants sont overlay2, btrfs, zfs et vfs. Le pilote de stockage affecte la façon dont les couches sont stockées et la façon dont l'invalidation du cache fonctionne. Pour la plupart des systèmes Linux, overlay2 est recommandé. Si vous êtes sur vfs, les builds seront considérablement plus lents et les performances du cache seront médiocres.
Vérifier l'espace disque et la taille du cache
docker system df
Cela montre l'utilisation du disque par les images, les conteneurs, les volumes locaux et le cache de build. La colonne Build Cache apparaît uniquement avec BuildKit. Si elle est importante, ce n'est pas nécessairement mauvais, mais si la pression du disque provoque des évictions, vous pouvez voir des échecs de cache. Surveillez régulièrement l'espace disque ; un disque plein est une cause fréquente d'invalidation inattendue du cache.
Inspecter le contexte de build
Le contexte de build est tout ce que vous envoyez au démon Docker pour un build. Un contexte volumineux ralentit les builds et peut inclure des fichiers qui invalident le cache inutilement. Utilisez .dockerignore pour exclure les fichiers non pertinents :
# .dockerignore
.git
*.log
node_modules
tmp
Sans un .dockerignore approprié, une modification dans un fichier journal ou un répertoire .git invalidera les couches qui copient tout le contexte. C'est une source fréquente d'échecs de cache.
Séparer l'observation de l'intervention
Capturez toujours l'état actuel et les horodatages d'abord. Protégez les informations d'identification et le matériel privé. Ensuite seulement, effectuez un changement limité lorsque vous comprenez son rayon d'impact et son chemin de récupération. Par exemple, si vous soupçonnez que le cache n'est pas utilisé, ne le nettoyez pas immédiatement. Au lieu de cela, exécutez docker buildx du pour voir l'utilisation du cache, et inspectez quelles couches sont reconstruites avec docker build --progress=plain.
Chemin de configuration sûr
Cette section couvre comment configurer et tester en toute sécurité les changements du cache de construction Docker. Le principe est : faire le plus petit changement justifié et vérifier son effet avant de l'appliquer à la production.
Activer BuildKit explicitement
Pour vous assurer que BuildKit est utilisé pour tous les builds, vous pouvez définir la variable d'environnement :
export DOCKER_BUILDKIT=1
Ou configurer le démon Docker (/etc/docker/daemon.json) avec :
{
"features": {
"buildkit": true
}
}
Puis redémarrez Docker :
sudo systemctl restart docker
Vérifiez avec docker buildx ls que le constructeur par défaut est maintenant BuildKit.
Configurer les montages de cache dans le Dockerfile
BuildKit vous permet de monter un répertoire de cache qui persiste entre les builds, même si la couche qui l'utilise est invalidée. Par exemple, pour un projet Node.js :
# syntax=docker/dockerfile:1.4
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm \
npm install
COPY . .
RUN npm run build
Le --mount=type=cache sur la commande npm install conserve le cache npm entre les builds. Sans lui, toute modification de package.json forcerait une réinstallation complète. Avec lui, seuls les paquets modifiés sont téléchargés.
Tester dans un environnement de préproduction
Ne modifiez jamais la configuration du cache directement en production. Utilisez un hôte Docker de préproduction ou un environnement local qui imite la production. Par exemple, créez un fichier Compose de test :
# docker-compose.test.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
image: myapp:test
Exécutez un build avec une sortie verbeuse pour voir les succès de cache :
docker compose -f docker-compose.test.yml build --progress=plain
Recherchez CACHED dans la sortie pour les couches qui devraient être réutilisées. Si une couche est reconstruite de manière inattendue, inspectez le Dockerfile et le contexte.
Vérification de la persistance des données
Lorsque vous traitez avec des volumes et des montages liés, un petit test similaire à la production devrait inclure un test de redémarrage. Créez un conteneur avec un volume nommé :
docker run -d --name app -v app_data:/var/lib/app myapp:latest
Écrivez un fichier de test, arrêtez et recréez le conteneur, et confirmez que le fichier persiste :
docker exec app sh -c 'echo test > /var/lib/app/test.txt'
docker stop app
docker rm app
docker run -d --name app -v app_data:/var/lib/app myapp:latest
docker exec app cat /var/lib/app/test.txt
Si le fichier n'est pas là, le service écrivait dans le système de fichiers du conteneur au lieu du volume. C'est une erreur courante liée au cache lorsque le processus de build suppose que les données persisteront.
Vérification et diagnostic
Cette section se concentre sur la façon de vérifier que le cache de build fonctionne correctement et de diagnostiquer quand ce n'est pas le cas.
Observer les succès de cache avec une progression simple
La sortie de build par défaut masque les informations détaillées du cache. Utilisez --progress=plain pour voir chaque couche et son état de cache :
docker build --progress=plain -t myapp:latest .
Exemple de sortie :
#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 32B done
#1 DONE 0.0s
#2 [internal] load .dockerignore
#2 transferring context: 2B done
#2 DONE 0.0s
#3 [internal] load metadata for docker.io/library/node:20-alpine
#3 DONE 0.6s
#4 [1/4] FROM docker.io/library/node:20-alpine
#4 CACHED
#5 [2/4] WORKDIR /app
#5 CACHED
#6 [3/4] COPY package*.json ./
#6 CACHED
#7 [4/4] COPY . .
#7 DONE 0.1s
Les lignes CACHED vous indiquent que la couche a été réutilisée. Si une couche affiche DONE au lieu de CACHED, elle a été reconstruite. Vérifiez ce qui a changé dans le contexte ou les instructions du Dockerfile.
Utiliser docker buildx du pour l'utilisation du cache
docker buildx du
Cela montre l'utilisation du cache par constructeur. Si vous voyez une valeur élevée, le cache est volumineux. S'il est vide ou petit, le cache a peut-être été récemment nettoyé.
Inspecter les métadonnées du cache
BuildKit stocke les métadonnées du cache dans sa base de données interne. Vous pouvez voir les entrées du cache avec :
docker buildx du --verbose
Cela produit des enregistrements de cache détaillés, y compris la commande qui a créé la couche et la clé de cache. C'est inestimable pour déboguer pourquoi une couche est invalidée.
Diagnostiquer les échecs de cache courants
- Changement d'instruction dans le Dockerfile : Toute modification du texte de l'instruction modifie la clé de cache pour cette couche et toutes les couches suivantes.
- Changement de fichier de contexte : Une modification dans un fichier du contexte (non exclu par
.dockerignore) qui est copié dans l'image invalidera la coucheCOPYet toutes les couches suivantes. - Changement des arguments de build : L'utilisation de
ARGet--build-argavec des valeurs changeantes invalide les couches qui utilisent cet argument. - Changement de l'image de base : Si l'image de base est mise à jour (même avec la même étiquette), toutes les couches basées sur elle peuvent être invalidées. Épingler le digest de l'image de base empêche une invalidation inattendue.
- Problèmes d'exportation/importation du cache BuildKit : Si vous utilisez des caches distants (par exemple, cache de registre), des problèmes de réseau ou d'authentification peuvent provoquer des échecs de cache.
Exécutez toujours docker build --progress=plain pour voir quelle couche est reconstruite, puis remontez à sa dépendance.
Modes d'échec et récupération
Même avec une configuration soignée, les échecs de cache se produisent. Cette section décrit les modes d'échec courants et les étapes de récupération.
Échec : Le cache n'est jamais touché
Symptôme : Chaque build reconstruit toutes les couches.
Causes possibles :
- BuildKit non activé (utilisation du constructeur hérité sans support de cache pour certaines fonctionnalités).
.dockerignoremanquant, provoquant des changements de contexte qui invalident les couchesCOPY.- Utilisation de
ADDavec une URL ou une archive qui change. - Exécution des builds en tant qu'utilisateurs différents ou avec des arguments de build différents.
Récupération :
- Activez BuildKit.
- Ajoutez un
.dockerignorerobuste. - Utilisez
COPYau lieu deADDlorsque c'est possible. - Standardisez l'environnement de build : même utilisateur, même commande de build, même digest d'image de base.
Échec : Le cache est périmé
Symptôme : Les builds sont rapides mais l'image résultante ne contient pas le dernier code ou les dernières dépendances.
Causes possibles :
- Le cache est réutilisé de manière incorrecte en raison d'un bug ou d'une mauvaise configuration.
- Le cache distant est désynchronisé.
- Utilisation d'étiquettes mutables pour les images de base ou les dépendances.
Récupération :
- Forcez une reconstruction avec
--no-cachepour obtenir une image fraîche. - Épinglez les images de base par digest.
- Épinglez les versions des dépendances dans votre manifeste de paquets.
- Pour les caches distants, assurez-vous qu'ils sont mis à jour correctement.
Échec : Disque plein à cause du cache
Symptôme : Le démon Docker signale des erreurs de manque d'espace sur le périphérique, les builds échouent de manière imprévisible.
Récupération :
- Nettoyez le cache avec
docker builder prune(avec--filterpour conserver le cache récent). - Configurez une tâche cron pour purger régulièrement l'ancien cache.
- Utilisez des montages de cache et des caches distants pour réduire les besoins de stockage local.
- Déplacez le répertoire de données Docker vers un disque plus grand si nécessaire.
Échec : Préoccupations de sécurité avec le cache
Symptôme : Des données sensibles (par exemple, des secrets) sont trouvées dans les couches du cache.
Récupération :
- Utilisez les secrets BuildKit (
--secret) pour éviter d'incorporer des secrets dans les couches. - Évitez de copier des fichiers
.envou des clés dans l'image. - Analysez périodiquement les images à la recherche de secrets.
- Si une fuite se produit, faites pivoter les secrets immédiatement et purgez le cache.
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle comme manuel pour gérer le cache de construction Docker en production. Chaque élément comprend une commande ou une vérification concrète.
1. Vérifier l'environnement
- [ ] Version de Docker :
docker version(notez les versions client et serveur). - [ ] BuildKit activé :
docker buildx lsmontre le driver BuildKit. - [ ] Pilote de stockage :
docker info --format '{{.Driver}}'estoverlay2ou un pilote haute performance similaire. - [ ] Espace disque :
docker system dfmontre suffisamment d'espace libre sur l'hôte de build.
2. Inspecter le contexte de build et le Dockerfile
- [ ]
.dockerignoreest présent et exclut les fichiers inutiles. - [ ] Le Dockerfile utilise des builds multi-étapes pour minimiser la taille de l'image finale.
- [ ] Les montages de cache sont utilisés pour les gestionnaires de paquets et les dépendances de build.
- [ ] Les images de base sont épinglées par digest pour la reproductibilité.
- [ ] Les valeurs
ARGchangeantes ne sont pas utilisées dans les premières couches sauf si nécessaire.
3. Tester le comportement du cache
- [ ] Exécutez
docker build --progress=plainet examinez l'état du cache pour chaque couche. - [ ] Identifiez toute couche reconstruite de manière inattendue et déterminez la cause.
- [ ] Exécutez deux builds consécutifs sans modification ; le second devrait avoir toutes les couches
CACHED. - [ ] Testez l'invalidation du cache : modifiez un fichier et confirmez que seules la couche affectée et les couches suivantes sont reconstruites.
4. Surveiller et maintenir
- [ ] Configurez la surveillance de l'espace disque sur l'hôte Docker.
- [ ] Planifiez régulièrement
docker builder pruneavec des filtres appropriés (conservez le cache des 7 derniers jours). - [ ] Envisagez d'utiliser un cache distant (par exemple,
--cache-fromavec un registre) pour les pipelines CI/CD. - [ ] Documentez toute configuration de cache personnalisée dans le dépôt du projet.
5. Procédures de récupération
- [ ] En cas de suspicion de corruption du cache, purgez avec
docker builder prune -aet reconstruisez à partir de zéro. - [ ] Si les builds sont lents en raison d'échecs de cache, vérifiez les changements de contexte et
.dockerignore. - [ ] En cas d'incident de sécurité impliquant le cache, faites pivoter les secrets et purgez le cache affecté.
6. Propriété et revue
- Propriétaire : Ingénieur DevOps (ou ingénieur plateforme) – nommez une seule personne responsable de l'infrastructure de build Docker.
- Fréquence de revue : Revue mensuelle des performances et de la configuration du cache. Le propriétaire doit vérifier les taux de succès du cache, l'utilisation du disque et tout incident récent. Pour les projets à forte évolution, une revue hebdomadaire peut être nécessaire.
Pièges courants et comment les éviter
- Ne pas utiliser
.dockerignore– Le contexte devient énorme, et toute modification mineure de fichier invalide des couches entières. Pourquoi cela arrive : Les développeurs commencent souvent sans.dockerignoreet oublient de l'ajouter. Éviter : Ajoutez un.dockerignoredès le départ avec des exclusions courantes. Récupérer : Ajoutez le.dockerignoreet reconstruisez ; les performances du cache s'améliorent.
- Utiliser l'étiquette
latestpour les images de base – L'image de base peut changer, invalidant toutes les couches. Pourquoi : Commodité ; les développeurs ne veulent pas mettre à jour les digests. Éviter : Épinglez les digests dans les lignesFROMet utilisez Dependabot pour les mises à jour. Récupérer : Si une image de baselatestchange et casse votre build, identifiez le nouveau digest et épinglez-le.
- Ne pas activer BuildKit – Manquer des fonctionnalités de cache avancées comme les montages de cache et la mise en cache inline. Pourquoi : Ne pas connaître BuildKit ou utiliser une ancienne version de Docker. Éviter : Mettez à niveau Docker et activez BuildKit par défaut. Récupérer : Activez BuildKit et adaptez le Dockerfile pour utiliser les montages de cache.
- Utiliser
ADDau lieu deCOPY–ADDpeut récupérer des URL distantes ou extraire des archives tar, provoquant une invalidation surprenante du cache. Pourquoi : Habitude ou malentendu. Éviter : UtilisezCOPYpour les fichiers locaux ; utilisezRUN curlpour les téléchargements distants séparément. Récupérer : RemplacezADDparCOPYpour stabiliser le cache.
- Construire sans cache dans la CI – Les pipelines CI exécutent souvent
docker buildsans cache, gaspillant du temps et des ressources. Pourquoi : Manque de persistance du cache entre les exécutions CI. Éviter : Utilisez un cache distant (par exemple,--cache-fromavec un registre) ou un démon BuildKit persistant (par exemple,docker buildxavec driver remote). Récupérer : Implémentez une stratégie de cache dans la CI pour accélérer les builds.
- Ignorer la gestion du disque – Le cache de build croît avec le temps et remplit le disque, provoquant des échecs. Pourquoi : Pas de surveillance ni de maintenance. Éviter : Configurez des alertes pour l'utilisation du disque et planifiez
docker builder prune. Récupérer : Purgez le cache et ajoutez une tâche cron.
- Incorporer des secrets dans les images – Des secrets comme les clés API finissent dans les couches du cache, devenant un risque de sécurité. Pourquoi : Copier des fichiers
.envou passer des secrets comme arguments de build. Éviter : Utilisez--secretavec BuildKit ou des secrets au moment de l'exécution. Récupérer : Faites pivoter les secrets exposés, purgez le cache et corrigez le Dockerfile.
Conclusion
Le cache de construction Docker en production n'est pas une fonctionnalité à configurer et oublier. Il nécessite une connaissance des versions, une configuration soignée, une surveillance et une planification de la récupération. La liste de contrôle et les exemples de cet article fournissent un cadre pratique pour garantir que vos builds sont rapides, cohérents et sécurisés.
Commencez par une vérification à faible risque : exécutez docker build --progress=plain sur un projet représentatif et examinez quelles couches sont mises en cache. Enregistrez l'état actuel, comparez avec l'attendu, puis décidez si des changements sont nécessaires. N'oubliez pas que chaque changement doit être petit, observable et réversible lorsque c'est possible.
Un flux de travail opérationnel fiable rend les échecs visibles, protège les valeurs sensibles, limite les changements à la ressource prévue et définit la vérification de la récupération avant qu'un incident ne force la décision. En suivant cette liste de contrôle, vous pouvez maîtriser le cache de construction Docker dans votre environnement de production.