
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 »| 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 »# Télécharger la dernière version (v0.13.1)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"Pour les distributions 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"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 »Dive propose une interface terminal interactive (TUI) pour explorer les couches d’une image.
Lancer l’analyse
Section intitulée « Lancer l’analyse »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 »| 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é.
Métriques clés
Section intitulée « Métriques clés »| 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 »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 »Dive peut bloquer automatiquement les builds si l’image ne respecte pas les critères d’efficacité.
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 »stages: - build - analyze
build-image: stage: build image: docker:27.5.1 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 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 »name: Analyze Docker Image
on: push: branches: [main]
jobs: analyze: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4.2.2
- name: Build image run: docker build -t myapp:${{ github.sha }} .
- name: Install Dive run: | 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"
- 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 »Pour intégrer les métriques dans vos outils de monitoring ou dashboards :
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 supporte plusieurs sources d’images :
Image Docker locale
Section intitulée « Image Docker locale »dive myimage:1.0.0# ou explicitementdive docker://myimage:1.0.0Image Podman
Section intitulée « Image Podman »dive podman://myimage:1.0.0Archive Docker (tar)
Section intitulée « Archive Docker (tar) »# 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 »# ❌ 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 »# ❌ 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 »# 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.6COPY --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 »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) »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 »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