Passer au contenu principal

Images (Docker)

Optimisation d'images

Une image de production de 1 Go où 50 Mo suffiraient, c'est du temps de déploiement perdu, de la bande passante gaspillée, et une surface d'attaque inutilement large. L'optimisation n'est pas du cosmétique.

Choix de l'image de base

  • debian:13-slim : Debian minimal, bonne compatibilité, ~75 Mo
  • alpine:3.x : très léger (~8 Mo), mais musl libc peut causer des incompatibilités avec certains binaires compilés pour glibc
  • distroless (gcr.io/distroless/*) : image Google sans shell, sans gestionnaire de paquets, sans utilisateur root par défaut. Recommandé pour les binaires compilés (Go, Rust)
  • scratch : image vide. Pour les binaires statiques uniquement

Réduire et fusionner les layers

# Mauvais : 3 layers, cache de paquets conservé
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*

# Bon : 1 layer, cache nettoyé dans la même commande
RUN apt-get update     && apt-get install -y --no-install-recommends curl     && rm -rf /var/lib/apt/lists/*

.dockerignore efficace

# Exclure tout, puis ré-inclure ce qui est nécessaire
*
!/src
!/requirements.txt
!/Makefile

Cette approche inverse est plus sûre : on ne risque pas d'oublier d'exclure un fichier sensible.

Inspecter ce qui prend de la place

# Analyser les layers et leur taille
docker history monapp:latest

# Outil dive : explore interactivement le contenu de chaque layer
# https://github.com/wagoodman/dive
dive monapp:latest

ARG vs ENV pour les secrets

Les valeurs ENV sont visibles dans les métadonnées de l'image (docker inspect). Ne jamais passer de secrets via ENV ou ARG dans un Dockerfile.

# Les secrets de build passent via BuildKit (non stockés dans les layers)
docker build --secret id=npmrc,src=$HOME/.npmrc .

# Dans le Dockerfile
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm install

Squash et export

# Exporter le filesystem d'un container (aplati, sans layers)
docker export $(docker create monapp:latest) | docker import - monapp:flat

# Avec BuildKit : --squash consolide tous les layers en un seul
docker build --squash -t monapp:squashed .

Le squash supprime l'historique des layers et empêche le partage de cache avec d'autres images. À utiliser avec parcimonie, principalement pour distribuer des images finales.