Aller au contenu
Contactez-nous
  1. Accueil
  2. /
  3. Blog
  4. /
  5. Images distroless et Chainguard : des conteneurs sans shell

Conteneurs
Sécurité

Images distroless et Chainguard : des conteneurs sans shell

14 juillet 2026

8 min de lecture

Sommaire
Le poids mort d'une image classique
Distroless : le runtime, rien que le runtime
Multi-stage build : compiler lourd, livrer léger
Chainguard et Wolfi : presque zéro CVE, signé
Débugger sans shell
Verdict ops
Sources

Un scan Trivy sur une image basée Debian remonte une centaine de CVE. On corrige, on rebuild, on rescanne : il en reste presque autant la semaine suivante. Le problème n'est pas le scanner, il fait son travail. Le problème, c'est ce qu'on a mis dans l'image. Un système d'exploitation complet sous une application qui n'en utilise que dix pour cent. Shell, gestionnaire de paquets, des centaines de binaires, des bibliothèques système : autant de surface d'attaque et de CVE à patcher, pour du code que l'application ne touche jamais.

La réponse tient en une phrase : ne mettre dans l'image que ce que l'application exécute, et rien d'autre. Pas de shell, pas d'apt, pas de coreutils. Distroless.

Le poids mort d'une image classique

Partir de debian:bookworm ou ubuntu:24.04, c'est embarquer une distribution entière. Un bash, un apt ou un dpkg, des dizaines d'utilitaires sous /bin et /usr/bin, un trousseau de bibliothèques partagées. Pour faire tourner un binaire Go statique ou une application Node, on traîne tout un userland dont on n'a pas besoin.

Deux coûts directs. La surface d'attaque : chaque binaire présent est un outil potentiel pour qui prend pied dans le conteneur. Un shell, c'est l'escalade et le mouvement latéral facilités. curl, wget, un interpréteur, tout ce qui aide un attaquant à télécharger un payload ou explorer l'hôte. La charge de patching : chaque paquet de la distribution génère ses CVE. On passe son temps à corriger des vulnérabilités dans des composants que l'application n'appelle jamais, juste parce qu'ils sont dans l'image. C'est exactement le réflexe d'images minimales qu'on évoquait en clôture du hardening Docker en production, poussé à son terme.

Réduire l'image, ce n'est pas une optimisation de taille. C'est de la réduction de surface d'attaque, donc de la sécurité.

Distroless : le runtime, rien que le runtime

Le projet distroless de Google produit des images qui contiennent l'application et ses dépendances d'exécution, sans shell ni gestionnaire de paquets ni aucun des programmes d'une distribution Linux standard. La base est Debian, mais réduite à la portion strictement nécessaire pour exécuter une classe de programmes.

Il y a des variantes par langage et des bases génériques. gcr.io/distroless/static pour un binaire statique (un Go compilé en static), de l'ordre de 2 Mio. gcr.io/distroless/base pour un binaire dynamique qui a besoin de la glibc. gcr.io/distroless/cc quand il faut aussi la libstdc++. Des images dédiées pour Java, Python, Node. Toutes partagent le même principe : zéro shell, zéro outil superflu.

Conséquence directe : on ne peut pas docker exec -it conteneur sh dans une image distroless. Il n'y a pas de sh. C'est précisément l'effet recherché, et ça change la façon de débugger, on y revient.

Multi-stage build : compiler lourd, livrer léger

Le mécanisme qui rend distroless utilisable, c'est le build multi-stage. On compile dans une image lourde qui a tout l'outillage, puis on copie uniquement l'artefact fini dans l'image finale minimale. Le compilateur, les en-têtes, les dépendances de build restent dans l'étage intermédiaire et ne suivent jamais dans l'image livrée.

# Étage 1 : build, image lourde avec le toolchain Go
FROM golang:1.24 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# binaire statique, sans dépendance dynamique
RUN CGO_ENABLED=0 go build -o /app/server ./cmd/server

# Étage 2 : image finale distroless, en non-root
FROM gcr.io/distroless/static-debian13:nonroot
COPY --from=build /app/server /server
USER nonroot:nonroot
ENTRYPOINT ["/server"]

L'image finale contient le binaire server, les certificats CA, le strict nécessaire. Pas de Go, pas de shell, pas de go mod. Le tag :nonroot impose un UID non privilégié, et la directive USER nonroot interdit l'exécution en root dans le conteneur. Combiner les deux, c'est la règle : un conteneur de production n'a aucune raison de tourner en root.

Pour un binaire vraiment autonome, on peut descendre sous distroless, jusqu'à scratch : une image vide, zéro octet de base. On y copie le binaire statique et ses certificats, point. C'est le minimum absolu, à condition que le binaire n'ait strictement aucune dépendance externe (pas de glibc, pas de résolution DNS via nsswitch, certificats embarqués). Distroless reste plus confortable parce qu'il fournit déjà CA, fuseaux horaires et utilisateur non-root.

Chainguard et Wolfi : presque zéro CVE, signé

Distroless de Google a un angle mort : la base Debian, et son rythme de mise à jour. Chainguard a repris l'idée avec une approche différente. Ses images sont construites avec apko et melange, à partir de Wolfi, une distribution Linux minimale conçue pour les charges cloud avec la sécurité de la chaîne d'approvisionnement comme priorité.

La plupart des images Chainguard sont distroless au même sens : application et dépendances d'exécution, sans shell ni gestionnaire de paquets. La différence tient à trois choses. Le rythme de mise à jour, conçu pour ramener le compte de CVE proche de zéro et corriger vite quand une vulnérabilité tombe. La construction depuis Wolfi plutôt que Debian, que Chainguard juge plus maintenable et plus facile à étendre. Et la signature : les images sont signées, ce qui permet d'en vérifier la provenance avant de les exécuter.

Côté distroless de Google aussi, les images sont signées par cosign en mode keyless. Vérifier la signature d'une image de base avant de la déployer, c'est la brique provenance de la chaîne d'approvisionnement. Le scan de vulnérabilités reste le complément indispensable : une image distroless n'est pas magiquement sans faille, elle a juste beaucoup moins de surface à scanner. On garde Trivy dans le pipeline pour le scan des images, simplement il remonte beaucoup moins de bruit.

Chainguard fournit aussi des variantes -dev qui, elles, embarquent un shell et des outils. Réservées au développement et au débogage, elles ne partent jamais en production.

Débugger sans shell

L'objection immédiate : « sans shell, comment je débugge un conteneur qui plante en prod ? ». La réponse n'est pas de remettre un shell dans l'image. C'est de débugger depuis l'extérieur, avec un conteneur de debug éphémère.

Sur Kubernetes, kubectl debug injecte un conteneur éphémère dans un pod qui tourne. Ce conteneur de debug, lui, embarque le shell et les outils qu'on veut, et il partage l'espace de processus, le réseau et les montages du conteneur cible, sans le modifier ni redémarrer le pod. Les conteneurs éphémères sont stables dans Kubernetes depuis la version 1.25.

# injecter un conteneur de debug outillé dans un pod en cours d'exécution
kubectl debug -it mon-pod --image=busybox --target=mon-conteneur

On obtient son shell, ses outils, sa visibilité sur les processus et le réseau du conteneur visé, le temps de l'investigation. Le conteneur de prod, lui, reste distroless. La sécurité n'est pas sacrifiée au débogage : on outille au moment du diagnostic, pas en permanence. C'est exactement le bon arbitrage. Le même principe vaut hors Kubernetes, où des outils comme cdebug attachent un conteneur outillé à un conteneur distroless qui tourne.

Cette logique de minimalisme et d'exécution non privilégiée prolonge la même ligne que Podman et son approche rootless, et l'image qui en résulte est ensuite exécutée par un runtime comme containerd au niveau de l'orchestrateur.

Verdict ops

Une image de production se construit en multi-stage et se livre en distroless ou en Chainguard. Le shell, le gestionnaire de paquets et les utilitaires système ne sont que de la surface d'attaque et un robinet à CVE pour du code que l'application n'exécute pas. On compile lourd, on livre léger, on tourne en non-root.

Entre les deux familles, le critère, c'est le rythme de patching et l'exigence de provenance. Distroless de Google fait le travail de base et reste un défaut solide. Chainguard, sur Wolfi, vise un compte de CVE proche de zéro et des mises à jour rapides, ce qui le justifie quand la pression réglementaire ou la criticité l'exige. L'argument « sans shell, on ne peut pas débugger » ne tient pas : kubectl debug et les conteneurs éphémères font le diagnostic depuis l'extérieur, sans jamais rouvrir la surface en production. Le shell n'a rien à faire dans une image de prod, fin du débat.

Sources

  • GoogleContainerTools/distroless : GitHub : dépôt officiel : variantes static, base, cc, par langage, tags nonroot et debug, signature cosign keyless
  • Overview of Chainguard Containers : Chainguard Academy : construction apko/melange depuis Wolfi, images distroless sans shell, variantes -dev
  • Debugging distroless container images : Chainguard Academy : méthode de débogage d'une image sans shell via conteneur de debug
  • Ephemeral Containers : Kubernetes : conteneurs éphémères et kubectl debug, stables depuis Kubernetes 1.25
  • Wolfi : GitHub : distribution minimale orientée sécurité de la chaîne d'approvisionnement servant de base aux images Chainguard
Besoin d'aide sur ce sujet ?

Notre équipe d'experts est là pour vous accompagner dans vos projets d'infrastructure et d'infogérance.

Contactez-nous

Articles similaires

Sigstore et Cosign : signer et vérifier les images conteneurs
Sécurité
Conteneurs
DevOps

Sigstore et Cosign : signer et vérifier les images conteneurs

Architecture Sigstore, signature d'images Cosign keyless, OIDC, Rekor, attestations SLSA. Mise en oeuvre dans un pipeline CI/CD et un cluster Kubernetes.

27 mai 2026

Lire plus

Matrix Synapse : messagerie fédérée self-hosted pour entreprise
Entreprise
Conteneurs
Sécurité

Matrix Synapse : messagerie fédérée self-hosted pour entreprise

Architecture Synapse, fédération Matrix, déploiement production, hardening, alternatives Dendrite et Conduit. Retour ops sur une stack messagerie souveraine.

26 mai 2026

Lire plus

Falco : runtime security eBPF pour Kubernetes en production
Sécurité
Kubernetes
Conteneurs

Falco : runtime security eBPF pour Kubernetes en production

Architecture Falco, eBPF, règles de détection, intégration Falcosidekick. Surveillance syscalls, container et K8s metadata, déploiement DaemonSet, retours ops.

25 mai 2026

Lire plus


SHPV, votre partenaire de confiance en infrastructure et infogérance informatique en France.

SHPV
Contactez-nousNous contacter
Expertise
InfrastructureDatacenterInfogéranceCloudHébergementTransit IP
Légales
Conditions Générales de VenteCPS - Contrat de ServicesCPS - Hébergement CloudCPS - Microsoft 365Accord sous-traitance RGPDTarifs interventions

SHPV © 2026 - Tous droits réservés

Mentions légalesPolitiques de confidentialité
SHPV FRANCE - SAS au capital de 16 000 € - 52 Rue Romain Rolland, 71230 Saint-Vallier - SIRET n°80886287400035 - R.C.S. Chalon-sur-Saône. Par téléphone 09 72 310 818 - Email: support@shpv.fr