Aller au contenu

Dive, plus d'excuse pour optimiser vos images Docker

Découvrez Dive, un outil pour inspecter les images Docker couche par couche et comprendre pourquoi elles pèsent si lourd.

Outils4 min de lecture

Logo Docker

Dans ma quête d'optimisation de ma CI, je me suis penché sur le build des images Docker, et surtout sur le temps que pouvait prendre chacune d'entre elles. Je suis finalement tombé sur Dive, un outil qui paraît simpliste mais qui fait gagner un temps fou quand on a besoin de comprendre « pourquoi mon image Docker fait 1 Go ».

Ce que fait Dive#

Une image Docker, c'est un empilement de couches (les layers), en gros une par instruction RUN, COPY ou ADD de votre Dockerfile. Dive sépare votre image en couches et vous permet de voir le contenu de chacune, sous forme d'arborescence comme un tree, directement dans le terminal.

Concrètement, il répond à trois questions.

  • Quelle couche pèse le plus lourd.
  • Quels fichiers chaque couche ajoute, modifie ou supprime.
  • Combien d'espace est gaspillé, par exemple un fichier écrit dans une couche puis écrasé ou supprimé dans une autre.

L'installer#

Dive est disponible dans la plupart des gestionnaires de paquets.

# macOS
brew install dive
 
# Arch Linux
pacman -S dive

Pour les autres distributions, il y a des .deb et des .rpm sur la page des releases du dépôt GitHub. Et si vous ne voulez rien installer, il tourne aussi dans un conteneur.

docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  wagoodman/dive nginx

L'utiliser#

Rien de plus simple, il suffit de taper dive suivi du nom de votre image.

dive nginx

Dive regarde d'abord si vous avez déjà l'image en local, sinon il va la chercher sur Docker Hub.

L'écran est découpé en plusieurs blocs.

  • Layers, en haut à gauche, liste chaque couche avec sa taille et la commande du Dockerfile qui l'a créée.
  • Layer Details donne l'identifiant et la commande complète de la couche sélectionnée.
  • Image Details, en bas à gauche, affiche la taille totale, l'espace gaspillé, un score d'efficacité et la liste des fichiers en cause.
  • Current Layer Contents, à droite, montre l'arborescence des fichiers de la couche.

On se déplace dans les couches avec les flèches, Tab passe d'un panneau à l'autre et Ctrl+F filtre l'arborescence. Ctrl+L n'affiche que ce que la couche sélectionnée change, Ctrl+A le résultat cumulé jusqu'à elle.

Lire le résultat#

Sur l'image nginx, on voit tout de suite que deux couches font presque toute la taille, 79 Mo pour l'image de base Debian et 84 Mo pour le RUN qui installe nginx. Le reste, ce sont des petits scripts de quelques Ko.

Côté efficacité, l'image s'en sort bien avec 98 % de score et 3,7 Mo gaspillés sur 163 Mo. Le gaspillage vient surtout des fichiers d'apt et de dpkg (/var/cache/debconf, /var/lib/dpkg/status…) présents dans l'image de base puis réécrits lors de l'installation de nginx. Chaque version reste stockée dans sa couche, même si seule la dernière est visible.

C'est exactement ce genre de chose que Dive rend visible. Par exemple, ce Dockerfile embarque tout le cache d'apt.

Dockerfile
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*

Alors que celui-ci ne garde que le nécessaire.

Dockerfile
RUN apt-get update \
  && apt-get install -y --no-install-recommends curl \
  && rm -rf /var/lib/apt/lists/*

Pour vérifier une image que vous construisez, dive build lance le build puis ouvre directement l'analyse.

dive build -t mon-app .

C'est aussi le moyen le plus rapide de repérer ce qui n'aurait jamais dû finir dans l'image, comme un node_modules de dev, un .git, un .env… Un coup d'œil à l'arborescence de la couche COPY . ., et on sait ce qu'il manque dans le .dockerignore.

Le mode CI#

Dive a aussi un mode non interactif, pensé pour la CI. Il analyse l'image et échoue si elle ne respecte pas vos seuils.

CI=true dive mon-app

Les seuils se règlent dans un fichier .dive-ci à la racine du projet.

.dive-ci
rules:
  # Score d'efficacité minimum, entre 0 et 1
  lowestEfficiency: 0.95
  # Espace gaspillé maximum
  highestWastedBytes: 20MB
  # Part maximale d'espace gaspillé, entre 0 et 1
  highestUserWastedPercent: 0.10

Perso, je n'utilise pas ce mode pour valider le build de mes images, mais je vous encourage à le tester chez vous, c'est un bon garde-fou contre une image qui grossit petit à petit sans que personne ne s'en rende compte.

En bref#

  • Dive montre le contenu de chaque couche d'une image Docker et l'espace gaspillé.
  • Un nettoyage ne sert à rien s'il n'est pas fait dans la même instruction que ce qu'il nettoie.
  • dive build permet de vérifier une image dès qu'on la construit, et le mode CI de bloquer celles qui dérapent.

Bref, Dive c'est idéal si vous voulez optimiser vos temps de build et vérifier que votre image n'embarque pas tout votre environnement de dev. Vous pouvez retrouver le projet et l'installer depuis son dépôt GitHub wagoodman/dive.