
Dive vous montre exactement ce qui se passe dans chaque couche de vos images Docker. En 5 minutes, vous saurez identifier les fichiers qui gaspillent de l'espace, comprendre pourquoi votre image est volumineuse, et intégrer une validation automatique dans vos pipelines CI/CD.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Explorer les couches : naviguer dans la structure interne d'une image avec l'interface TUI
- Identifier l'espace gaspillé : repérer les fichiers dupliqués ou inutiles entre couches
- Valider en CI/CD : bloquer les builds si l'efficacité est insuffisante
- Exporter en JSON : intégrer les métriques dans vos outils de monitoring
Ce que Dive sait faire
Section intitulée « Ce que Dive sait faire »Dive ne modifie ni ne reconstruit vos images : c'est un outil de lecture. Il ouvre l'image couche par couche et rapporte ce qu'il y trouve, à vous d'en tirer les corrections dans le Dockerfile. Deux usages cohabitent : l'exploration interactive, quand vous cherchez à comprendre, et le mode CI, qui rend un simple verdict de réussite ou d'échec.
| Fonctionnalité | Description |
|---|---|
| Exploration TUI | Interface terminal interactive pour naviguer dans les couches |
| Analyse d'efficacité | Calcul du pourcentage d'espace gaspillé |
| Mode CI | Validation automatique avec seuils configurables |
| Export JSON | Données structurées pour intégration externe |
| Multi-sources | Support Docker, Podman et archives |
Installation de Dive
Section intitulée « Installation de Dive »Dive est un binaire Go autonome, sans dépendance à installer. Il a en
revanche besoin d'accéder au moteur de conteneurs pour extraire les images :
appartenance au groupe docker ou socket Podman accessible. La version est
épinglée dans chaque commande, ce qui rend l'installation reproductible et
permet de vérifier l'empreinte du fichier téléchargé.
Le dépôt publie un fichier dive_<version>_checksums.txt qui contient
l'empreinte SHA-256 de chaque artefact. Téléchargez-le en même temps que le
paquet et refusez l'installation si la vérification échoue : c'est le seul moyen
de savoir que le fichier reçu est bien celui publié par le projet.
# Télécharger le paquet ET le fichier de sommes officiel (v0.13.1)DIVE_VERSION="0.13.1"DIVE_BASE="https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}"
curl -fsSLO "${DIVE_BASE}/dive_${DIVE_VERSION}_linux_amd64.deb"curl -fsSLO "${DIVE_BASE}/dive_${DIVE_VERSION}_checksums.txt"
# Vérifier l'empreinte, puis seulement installersha256sum --ignore-missing --check "dive_${DIVE_VERSION}_checksums.txt"sudo dpkg -i "dive_${DIVE_VERSION}_linux_amd64.deb"La commande de vérification doit afficher
dive_0.13.1_linux_amd64.deb: Réussi (ou OK en anglais). L'option
--ignore-missing est nécessaire car le fichier de sommes couvre toutes les
architectures publiées, dont vous n'avez téléchargé qu'un artefact.
Pour les distributions RPM (Fedora, RHEL), la démarche est identique, seule l'extension change :
DIVE_VERSION="0.13.1"DIVE_BASE="https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}"
curl -fsSLO "${DIVE_BASE}/dive_${DIVE_VERSION}_linux_amd64.rpm"curl -fsSLO "${DIVE_BASE}/dive_${DIVE_VERSION}_checksums.txt"
sha256sum --ignore-missing --check "dive_${DIVE_VERSION}_checksums.txt"sudo rpm -i "dive_${DIVE_VERSION}_linux_amd64.rpm"brew install divechoco install diveOu avec winget :
winget install wagoodman.diveASDF-VM permet de gérer plusieurs versions :
asdf plugin add diveasdf install dive 0.13.1asdf set --home dive 0.13.1go install github.com/wagoodman/dive@v0.13.1Vérification de l'installation :
dive --versionRésultat attendu :
dive 0.13.1Explorer une image avec l'interface TUI
Section intitulée « Explorer une image avec l'interface TUI »Une TUI (Terminal User Interface) est une interface graphique dessinée dans
le terminal, pilotée au clavier. Celle de Dive met en regard deux informations
qu'on ne peut pas croiser autrement : la commande du Dockerfile qui a produit
une couche et les fichiers que cette commande a réellement écrits. C'est là
que les surprises apparaissent, un apt-get install qui laisse 200 Mo de cache
par exemple.
Lancer l'analyse
Section intitulée « Lancer l'analyse »L'image doit déjà être présente localement : Dive ne la télécharge pas. L'analyse prend quelques secondes, plus longtemps sur une image volumineuse car l'outil extrait chaque couche.
dive nginx:1.27.3-alpineL'interface s'ouvre avec deux panneaux principaux :
- Panneau gauche : liste des couches avec leur taille et la commande Dockerfile associée
- Panneau droit : arborescence des fichiers de la couche sélectionnée
Navigation dans l'interface
Section intitulée « Navigation dans l'interface »Deux raccourcis changent la façon de lire l'image et méritent d'être retenus en
premier. Ctrl+Space bascule entre la vue d'une couche seule et la vue
agrégée, qui montre le système de fichiers tel qu'il sera au démarrage du
conteneur. Ctrl+B bascule l'affichage des fichiers inchangés, ce qui
permet d'isoler l'apport réel de la couche sélectionnée.
| Touche | Action |
|---|---|
Tab | Basculer entre les panneaux |
↑ / ↓ ou k / j | Naviguer dans les listes |
Space | Déplier/replier un dossier |
Ctrl+U / Ctrl+D | Page haut / Page bas |
Ctrl+A | Afficher les fichiers ajoutés |
Ctrl+R | Afficher les fichiers supprimés |
Ctrl+M | Afficher les fichiers modifiés |
Ctrl+B | Afficher tous les fichiers non modifiés |
Ctrl+Space | Basculer entre vue couche / vue agrégée |
Ctrl+L | Afficher les détails de la couche |
Ctrl+F | Filtrer les fichiers |
q | Quitter |
Comprendre les indicateurs visuels
Section intitulée « Comprendre les indicateurs visuels »Dans l'arborescence des fichiers, Dive utilise des codes couleur :
| Couleur | Signification |
|---|---|
| Vert | Fichier ajouté dans cette couche |
| Rouge | Fichier supprimé dans cette couche |
| Jaune | Fichier modifié dans cette couche |
| Blanc | Fichier inchangé (hérité des couches précédentes) |
Analyser l'efficacité d'une image
Section intitulée « Analyser l'efficacité d'une image »Au-delà de l'exploration visuelle, Dive calcule des métriques d'efficacité. Le principe est simple : un fichier écrit dans une couche puis réécrit ou supprimé dans une couche ultérieure occupe quand même la place des deux versions, car une couche ne peut jamais être modifiée après coup. C'est ce que Dive appelle l'espace gaspillé, et ce chiffre est comparable d'une construction à l'autre.
Métriques clés
Section intitulée « Métriques clés »Ces trois valeurs se lisent ensemble. L'efficiency donne l'impression générale, mais le userWastedPercent est le plus actionnable : il ne compte que le gaspillage causé par vos propres instructions, en écartant celui hérité de l'image de base sur laquelle vous ne pouvez rien.
| Métrique | Description | Seuil recommandé |
|---|---|---|
| efficiency | Pourcentage d'espace utilisé efficacement | ≥ 90% |
| wastedBytes | Octets gaspillés (fichiers dupliqués/supprimés) | ≤ 10 MB |
| userWastedPercent | Pourcentage d'espace gaspillé par les modifications utilisateur | ≤ 10% |
Exemple d'analyse
Section intitulée « Exemple d'analyse »L'option --ci désactive l'interface interactive et écrit le rapport sur la
sortie standard. Sans fichier de configuration, Dive applique ses règles par
défaut, d'où la ligne Using default CI config en tête de sortie.
dive nginx:1.27.3-alpine --ciRésultat :
Using default CI configImage Source: docker://nginx:1.27.3-alpineExtracting image from docker-engine... (this can take a while for large images)Analyzing image... efficiency: 99.1303 % wastedBytes: 657611 bytes (658 kB) userWastedPercent: 1.6763 %Inefficient Files:Count Wasted Space File Path 2 445 kB /etc/ssl/certs/ca-certificates.crt 3 160 kB /lib/apk/db/installed 3 49 kB /lib/apk/db/scripts.tar 2 1.5 kB /etc/passwd 2 1.0 kB /etc/group 2 547 B /etc/shadow 3 414 B /lib/apk/db/triggers 3 396 B /etc/apk/worldResults: PASS: highestUserWastedPercent SKIP: highestWastedBytes: rule disabled PASS: lowestEfficiencyResult:PASS [Total:3] [Passed:2] [Failed:0] [Warn:0] [Skipped:1]Interpréter les fichiers inefficaces
Section intitulée « Interpréter les fichiers inefficaces »La section "Inefficient Files" montre les fichiers qui apparaissent dans plusieurs couches (dupliqués) ou qui ont été supprimés après avoir été ajoutés.
Dans l'exemple ci-dessus :
ca-certificates.crtapparaît 2 fois → 445 kB gaspillés- Les fichiers APK (
installed,scripts.tar) sont modifiés à chaqueapk add
Intégrer Dive dans CI/CD
Section intitulée « Intégrer Dive dans CI/CD »En mode --ci, Dive termine avec un code de sortie non nul dès qu'une règle
échoue, ce qui fait tomber le job qui l'exécute. Vous transformez ainsi une
bonne pratique en contrainte vérifiée à chaque build. Commencez par des seuils
proches de ce que produisent déjà vos images : un seuil trop ambitieux d'emblée
casse la chaîne et pousse l'équipe à désactiver la vérification.
Configuration CI avec fichier .dive-ci
Section intitulée « Configuration CI avec fichier .dive-ci »Créez un fichier .dive-ci ou .dive-ci.yaml à la racine de votre projet :
rules: # Efficacité minimale (ratio 0-1) lowestEfficiency: 0.9 # Pourcentage max de gaspillage utilisateur (ratio 0-1) highestUserWastedPercent: 0.1 # Octets max gaspillés (disabled = pas de limite) highestWastedBytes: disabledExemple GitLab CI
Section intitulée « Exemple GitLab CI »Le job d'analyse tourne dans l'image officielle de Dive et doit atteindre le
même démon Docker que le job de build, d'où le service dind et la variable
DOCKER_HOST. Le allow_failure: false est explicite à dessein : sans lui, la
valeur par défaut du job resterait implicite alors que c'est justement le point
qui décide si le pipeline s'arrête.
stages: - build - analyze
build-image: stage: build image: docker:27.5.1@sha256:aa3df78ecf320f5fafdce71c659f1629e96e9de0968305fe1de670e0ca9176ce services: - docker:27.5.1-dind script: - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
analyze-image: stage: analyze image: wagoodman/dive:v0.13.1@sha256:f1886e6c32c094fc41a623c1989f5cb3e48aa766da5f0be233f911fc1d85ce10 services: - docker:27.5.1-dind variables: DOCKER_HOST: tcp://docker:2375 script: - dive $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --ci allow_failure: falseExemple GitHub Actions
Section intitulée « Exemple GitHub Actions »Sur GitHub Actions, Docker est déjà présent sur les runners hébergés : il n'y a
pas de service à déclarer. Trois précautions sont appliquées ici. L'action
checkout est épinglée par SHA avec son tag en commentaire, pour qu'une
republication du tag ne change pas le code exécuté. Le workflow part de
permissions: {} et le job ne récupère que contents: read. Enfin, l'empreinte
du paquet Dive est vérifiée avant installation, exactement comme sur un poste de
travail.
name: Analyze Docker Image
on: push: branches: [main]
permissions: {}
jobs: analyze: runs-on: ubuntu-24.04 timeout-minutes: 15 permissions: contents: read steps: - name: Récupérer le code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false
- name: Build image run: docker build -t "myapp:${GITHUB_SHA}" .
- name: Install Dive env: DIVE_VERSION: "0.13.1" run: | base="https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}" curl -fsSLO "${base}/dive_${DIVE_VERSION}_linux_amd64.deb" curl -fsSLO "${base}/dive_${DIVE_VERSION}_checksums.txt" sha256sum --ignore-missing --check "dive_${DIVE_VERSION}_checksums.txt" sudo dpkg -i "dive_${DIVE_VERSION}_linux_amd64.deb"
- name: Analyze image run: dive "myapp:${GITHUB_SHA}" --ciOptions CI en ligne de commande
Section intitulée « Options CI en ligne de commande »Vous pouvez surcharger les règles sans fichier de configuration :
dive myimage:1.0.0 --ci \ --lowestEfficiency 0.95 \ --highestUserWastedPercent 0.05 \ --highestWastedBytes 5MBExporter l'analyse en JSON
Section intitulée « Exporter l'analyse en JSON »Le mode --ci répond par oui ou non ; l'export JSON conserve le détail
chiffré. C'est ce qu'il faut pour suivre l'évolution de la taille d'une image
au fil des versions, ou pour alimenter un tableau de bord. Le fichier est écrit
à l'emplacement passé en argument, et l'interface interactive ne s'ouvre pas.
dive nginx:1.27.3-alpine --json /tmp/dive-report.jsonLe fichier JSON contient :
- La liste des couches avec leurs fichiers
- Les métriques d'efficacité
- Les fichiers inefficaces identifiés
Exemple d'extraction avec jq :
# Extraire les métriques globalescat /tmp/dive-report.json | jq '{ efficiency: .image.efficiency, sizeBytes: .image.sizeBytes, wastedBytes: .image.inefficientBytes}'Analyser différentes sources
Section intitulée « Analyser différentes sources »Dive ne se limite pas au démon Docker. Le préfixe placé devant le nom de l'image indique où aller la chercher : moteur Docker, moteur Podman ou fichier d'archive. Cette dernière possibilité est précieuse en CI, où l'image peut être analysée sans qu'aucun moteur de conteneurs ne tourne.
Image Docker locale
Section intitulée « Image Docker locale »C'est le comportement par défaut : sans préfixe, Dive interroge le démon Docker
désigné par DOCKER_HOST.
dive myimage:1.0.0# ou explicitementdive docker://myimage:1.0.0Image Podman
Section intitulée « Image Podman »Le préfixe podman:// s'adresse au stockage local de Podman, sans passer par un
démon. L'utilisateur qui lance la commande doit être celui qui possède les
images, les conteneurs rootless étant propres à chaque compte.
dive podman://myimage:1.0.0Archive Docker (tar)
Section intitulée « Archive Docker (tar) »docker save produit une archive contenant toutes les couches. Dive sait la
lire directement, ce qui permet d'analyser une image construite ailleurs ou
récupérée en tant qu'artefact de pipeline.
# Exporter avec docker savedocker save myimage:1.0.0 -o myimage.tar
# Analyser l'archivedive docker-archive://myimage.tarOptimiser ses images après analyse
Section intitulée « Optimiser ses images après analyse »Une fois les problèmes identifiés avec Dive, voici les actions correctives :
Combiner les commandes RUN
Section intitulée « Combiner les commandes RUN »Chaque instruction RUN crée une couche. Trois apk add successifs réécrivent
donc trois fois la base de données des paquets, et ce sont ces réécritures que
Dive signale dans les fichiers inefficaces. Une seule instruction produit une
seule version de chaque fichier.
# ❌ Mauvais : 3 couches, fichiers APK dupliquésRUN apk add curlRUN apk add jqRUN apk add git
# ✅ Bon : 1 couche, moins de gaspillageRUN apk add --no-cache curl jq gitNettoyer dans la même couche
Section intitulée « Nettoyer dans la même couche »C'est le piège le plus contre-intuitif : un rm -rf dans une couche ultérieure
n'allège rien. Le fichier reste stocké dans la couche qui l'a créé, la
suppression ne fait qu'ajouter une marque qui le masque. Le nettoyage doit avoir
lieu dans la même instruction que la création, ou mieux, ne jamais écrire le
cache grâce à --no-cache.
# ❌ Mauvais : le cache APK reste dans une couche précédenteRUN apk updateRUN apk add curlRUN rm -rf /var/cache/apk/*
# ✅ Bon : tout dans la même coucheRUN apk add --no-cache curlUtiliser des builds multi-stage
Section intitulée « Utiliser des builds multi-stage »Le multi-stage est la technique la plus efficace quand la compilation
demande des outils absents en production. Seuls les fichiers explicitement
recopiés avec COPY --from se retrouvent dans l'image finale : le compilateur,
les sources et les dépendances de build restent dans l'étape de construction et
disparaissent.
# Stage buildFROM golang:1.23-alpine AS builderWORKDIR /appCOPY . .RUN go build -o myapp
# Stage runtime (image finale légère)FROM alpine:3.20.6@sha256:de4fe7064d8f98419ea6b49190df1abbf43450c1702eeb864fe9ced453c1cc5fCOPY --from=builder /app/myapp /usr/local/bin/CMD ["myapp"]Pour plus de techniques d'optimisation, consultez le guide Optimiser la taille des images.
Dépannage
Section intitulée « Dépannage »Presque tous les problèmes rencontrés avec Dive relèvent de la même cause : l'outil n'atteint pas le moteur de conteneurs, ou n'y trouve pas l'image demandée. Les cas ci-dessous couvrent les quatre situations les plus fréquentes, de la plus courante à la plus spécifique.
Erreur "Cannot connect to Docker daemon"
Section intitulée « Erreur "Cannot connect to Docker daemon" »Vérifiez que Docker est démarré et que l'utilisateur a les permissions :
# Vérifier le daemondocker info
# Ajouter l'utilisateur au groupe dockersudo usermod -aG docker $USERnewgrp dockerErreur "image not found"
Section intitulée « Erreur "image not found" »L'image doit être présente localement. Téléchargez-la d'abord :
docker pull nginx:1.27.3-alpinedive nginx:1.27.3-alpineInterface TUI corrompue ou caractères étranges
Section intitulée « Interface TUI corrompue ou caractères étranges »Vérifiez que votre terminal supporte UTF-8 et les 256 couleurs :
export TERM=xterm-256colordive myimage:1.0.0Dive ne trouve pas le socket Docker (macOS/Colima)
Section intitulée « Dive ne trouve pas le socket Docker (macOS/Colima) »Dive s'adresse au socket désigné par DOCKER_HOST et ne devine pas les
emplacements alternatifs. Avec Colima ou Podman, ce chemin n'est pas celui par
défaut : il faut l'exporter dans le terminal, ou dans votre fichier de
configuration de shell pour ne plus y revenir.
export DOCKER_HOST="unix://${HOME}/.colima/default/docker.sock"# ou pour Podmanexport DOCKER_HOST="unix://${XDG_RUNTIME_DIR}/podman/podman.sock"À retenir
Section intitulée « À retenir »- Interface TUI :
dive <image>pour explorer visuellement les couches - Mode CI :
dive <image> --cipour validation automatique dans les pipelines - Efficacité ≥ 90% : seuil recommandé pour des images optimisées
- Combiner les RUN : évite la duplication de fichiers entre couches
- Multi-stage builds : séparent build et runtime pour des images légères
Prochaines étapes
Section intitulée « Prochaines étapes »Plus d'infos
Section intitulée « Plus d'infos »FAQ, Questions fréquentes
Section intitulée « FAQ, Questions fréquentes »Les questions ci-dessous reviennent le plus souvent lors des premières
utilisations de Dive : lecture des métriques d'efficacité, analyse sans démon
Docker, intégration en CI/CD et différence avec docker history.
Définition
Dive est un outil en ligne de commande créé par Alex Goodman pour explorer les couches internes des images Docker/OCI et identifier l'espace disque gaspillé.Fonctionnalités principales
| Fonctionnalité | Description |
|---|---|
| Interface TUI | Navigation interactive dans les couches et fichiers |
| Analyse d'efficacité | Calcul du % d'espace gaspillé |
| Mode CI | Validation automatique avec seuils configurables |
| Export JSON | Données structurées pour monitoring |
| Multi-sources | Docker, Podman, archives tar |
Cas d'usage
- Déboguer une image volumineuse : identifier les fichiers inutiles
- Optimiser les Dockerfiles : comprendre l'impact de chaque instruction
- CI/CD : bloquer les builds si l'efficacité est insuffisante
- Audit de sécurité : vérifier les fichiers présents dans l'image
Exemple rapide
# Explorer une image
dive nginx:1.27.3-alpine
# Valider en CI
dive myapp:1.0.0 --ci --lowestEfficiency 0.9
Installation via package deb (Ubuntu/Debian)
DIVE_VERSION="0.13.1"
curl -fsSLO "https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}/dive_${DIVE_VERSION}_linux_amd64.deb"
sudo dpkg -i "dive_${DIVE_VERSION}_linux_amd64.deb"
Installation via package rpm (Fedora/RHEL)
DIVE_VERSION="0.13.1"
curl -fsSLO "https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}/dive_${DIVE_VERSION}_linux_amd64.rpm"
sudo rpm -i "dive_${DIVE_VERSION}_linux_amd64.rpm"
Alternatives
# Homebrew (si installé)
brew install dive
# ASDF
asdf plugin add dive
asdf install dive 0.13.1
# Go install
go install github.com/wagoodman/dive@v0.13.1
Vérification
dive --version
# dive 0.13.1
Raccourcis principaux
| Touche | Action |
|---|---|
Tab |
Basculer entre panneaux (couches ↔ fichiers) |
↑ / ↓ |
Naviguer dans les listes |
j / k |
Navigation vim (haut/bas) |
Space |
Déplier/replier un dossier |
Ctrl+U / Ctrl+D |
Page haut / Page bas |
q |
Quitter |
Filtres de fichiers
| Touche | Affiche |
|---|---|
Ctrl+A |
Fichiers ajoutés (vert) |
Ctrl+R |
Fichiers supprimés (rouge) |
Ctrl+M |
Fichiers modifiés (jaune) |
Ctrl+B |
Fichiers inchangés |
Ctrl+Space |
Vue couche / vue agrégée |
Recherche
| Touche | Action |
|---|---|
Ctrl+F |
Filtrer par nom de fichier |
Ctrl+L |
Afficher détails de la couche |
Codes couleur
- Vert : fichier ajouté dans cette couche
- Rouge : fichier supprimé
- Jaune : fichier modifié
- Blanc : fichier inchangé (hérité)
Fichier de configuration .dive-ci.yaml
rules:
# Efficacité minimale (0-1)
lowestEfficiency: 0.9
# Gaspillage max utilisateur (0-1)
highestUserWastedPercent: 0.1
# Octets max gaspillés (ou 'disabled')
highestWastedBytes: disabled
GitLab CI
analyze-image:
stage: analyze
image: wagoodman/dive:v0.13.1
services:
- docker:27.5.1-dind
variables:
DOCKER_HOST: tcp://docker:2375
script:
- dive $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --ci
GitHub Actions
- name: Install Dive
run: |
curl -fsSLO https://github.com/wagoodman/dive/releases/download/v0.13.1/dive_0.13.1_linux_amd64.deb
sudo dpkg -i dive_0.13.1_linux_amd64.deb
- name: Analyze image
run: dive myapp:${{ github.sha }} --ci
Options ligne de commande
dive myimage:1.0.0 --ci \
--lowestEfficiency 0.95 \
--highestUserWastedPercent 0.05 \
--highestWastedBytes 10MB
Codes de sortie
0: validation réussie (PASS)1: validation échouée (FAIL)- Autres : erreur d'exécution
Les 3 métriques clés
| Métrique | Description | Seuil recommandé |
|---|---|---|
| efficiency | % d'espace utilisé efficacement | ≥ 90% |
| wastedBytes | Octets gaspillés (dupliqués/supprimés) | ≤ 10 MB |
| userWastedPercent | % de gaspillage par modifications utilisateur | ≤ 10% |
Exemple de sortie
efficiency: 99.1303 %
wastedBytes: 657611 bytes (658 kB)
userWastedPercent: 1.6763 %
Inefficient Files:
Count Wasted Space File Path
2 445 kB /etc/ssl/certs/ca-certificates.crt
3 160 kB /lib/apk/db/installed
Interpréter "Inefficient Files"
- Count > 1 : fichier présent dans plusieurs couches (dupliqué)
- Le fichier
ca-certificates.crt(445 kB) apparaît 2 fois → 445 kB gaspillés - Les fichiers APK sont modifiés à chaque
apk add
Causes fréquentes de gaspillage
- Instructions RUN séparées : chaque RUN crée une couche
- Fichiers supprimés après ajout : le fichier reste dans la couche précédente
- Cache package managers : apt, apk, pip créent des caches
Combiner les commandes RUN
# ❌ Mauvais : 3 couches, fichiers dupliqués
RUN apk add curl
RUN apk add jq
RUN apk add git
# ✅ Bon : 1 seule couche
RUN apk add --no-cache curl jq git
Nettoyer dans la même couche
# ❌ Mauvais : cache reste dans couche précédente
RUN apt update
RUN apt install -y curl
RUN rm -rf /var/lib/apt/lists/*
# ✅ Bon : nettoyage dans la même couche
RUN apt update && apt install -y curl \
&& rm -rf /var/lib/apt/lists/*
Utiliser --no-cache
# Alpine
RUN apk add --no-cache nginx
# Python pip
RUN pip install --no-cache-dir -r requirements.txt
Builds multi-stage
# Stage build (outils de compilation)
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp
# Stage runtime (image minimale)
FROM alpine:3.20.6
COPY --from=builder /app/myapp /usr/local/bin/
CMD ["myapp"]
Éviter de supprimer après coup
# ❌ Mauvais : fichier reste dans couche 1
RUN wget https://example.com/large-file.tar.gz
RUN tar -xzf large-file.tar.gz
RUN rm large-file.tar.gz # Ne libère pas l'espace !
# ✅ Bon : tout dans une couche
RUN wget https://example.com/large-file.tar.gz \
&& tar -xzf large-file.tar.gz \
&& rm large-file.tar.gz
Analyser une archive tar
# Exporter l'image en archive
docker save nginx:1.27.3-alpine -o nginx.tar
# Analyser l'archive (sans daemon)
dive docker-archive://nginx.tar
Avec Skopeo (pas besoin de Docker)
# Télécharger en archive
skopeo copy docker://nginx:1.27.3-alpine docker-archive:nginx.tar
# Analyser
dive docker-archive://nginx.tar
Analyser une image Podman
dive podman://myimage:1.0.0
Configurer le socket Docker
# Colima (macOS)
export DOCKER_HOST="unix://${HOME}/.colima/default/docker.sock"
# Podman rootless
export DOCKER_HOST="unix://${XDG_RUNTIME_DIR}/podman/podman.sock"
# Docker classique
export DOCKER_HOST="unix:///var/run/docker.sock"
dive myimage:1.0.0
Sources supportées
| Préfixe | Source |
|---|---|
docker:// |
Daemon Docker local (défaut) |
podman:// |
Daemon Podman local |
docker-archive:// |
Archive tar (docker save) |
Exporter en JSON
dive nginx:1.27.3-alpine --json /tmp/dive-report.json
Structure du fichier JSON
Le fichier contient :- layer : liste des couches avec leurs fichiers
- image : métriques globales (efficacité, taille, gaspillage)
Extraire les métriques avec jq
# Métriques globales
cat /tmp/dive-report.json | jq '{
efficiency: .image.efficiency,
sizeBytes: .image.sizeBytes,
wastedBytes: .image.inefficientBytes
}'
# Liste des couches
cat /tmp/dive-report.json | jq '.layer[] | {index, command, sizeBytes}'
# Fichiers d'une couche spécifique
cat /tmp/dive-report.json | jq '.layer[0].fileList | .[0:5]'
Intégration monitoring
# Extraire efficacité pour Prometheus/Grafana
EFFICIENCY=$(cat /tmp/dive-report.json | jq -r '.image.efficiency')
echo "docker_image_efficiency{image=\"myapp\"} $EFFICIENCY"
Combiner CI + JSON
# Valider ET exporter
dive myimage:1.0.0 --ci --json /tmp/report.json
Vérifier le daemon Docker
# Status du service
systemctl status docker
# Tester la connexion
docker info
Ajouter l'utilisateur au groupe docker
sudo usermod -aG docker $USER
# Recharger les groupes (ou se reconnecter)
newgrp docker
Configurer DOCKER_HOST
# Docker Desktop (macOS)
export DOCKER_HOST="unix://${HOME}/.docker/run/docker.sock"
# Colima (macOS)
export DOCKER_HOST="unix://${HOME}/.colima/default/docker.sock"
# Podman (Linux rootless)
export DOCKER_HOST="unix://${XDG_RUNTIME_DIR}/podman/podman.sock"
# Docker-in-Docker (CI)
export DOCKER_HOST="tcp://docker:2375"
Vérifier les permissions du socket
ls -la /var/run/docker.sock
# srw-rw---- 1 root docker 0 Jan 23 10:00 /var/run/docker.sock
# L'utilisateur doit être dans le groupe 'docker'
groups $USER
Alternative : utiliser une archive
# Si Docker inaccessible, exporter ailleurs et analyser l'archive
docker save myimage:1.0.0 -o myimage.tar
scp myimage.tar autre-machine:/tmp/
# Sur autre-machine (sans Docker)
dive docker-archive:///tmp/myimage.tar
Comparaison
| Fonctionnalité | docker history | Dive |
|---|---|---|
| Affiche les couches | ✅ Oui | ✅ Oui |
| Taille par couche | ✅ Oui | ✅ Oui |
| Commandes Dockerfile | ✅ Oui | ✅ Oui |
| Explorer les fichiers | ❌ Non | ✅ TUI interactive |
| Identifier fichiers gaspillés | ❌ Non | ✅ Oui |
| Métriques d'efficacité | ❌ Non | ✅ Oui |
| Mode CI | ❌ Non | ✅ Validation automatique |
| Export JSON | ❌ Non | ✅ Oui |
docker history
docker history nginx:1.27.3-alpine
# IMAGE CREATED CREATED BY SIZE
# 4e1b6... 2 weeks ago CMD ["nginx" "-g" "daemon off;"] 0B
# <missing> 2 weeks ago STOPSIGNAL SIGQUIT 0B
# ...
Limité à la liste des couches et tailles.Dive
dive nginx:1.27.3-alpine --ci
# efficiency: 99.1303 %
# wastedBytes: 657611 bytes
# Inefficient Files:
# 2 445 kB /etc/ssl/certs/ca-certificates.crt
Analyse détaillée avec identification des problèmes.Quand utiliser quoi ?
- docker history : aperçu rapide de la structure
- Dive : optimisation, débogage, CI/CD