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
!/MakefileCette 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:latestARG 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 installSquash 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.