Comment sécuriser sa images légères sans se compliquer la vie



Introduction

Les images conteneurs légères — alpine, distroless, scratch, slim — sont devenues le standard de facto pour le déploiement moderne. Elles démarrer plus vite, consomment moins de mémoire, réduisent la surface d’attaque. Pourtant, paradoxalement, adopter une image slim peut introduire des risques invisibles si l’on ne suit pas quelques principes fondamentaux.

Cet article propose une approche pragmatique : sécuriser ses images légères sans transformer chaque build en un exercice de compliance kafkaïen.


1. Comprendre pourquoi les images légères changent la donne sécuritaire

Une surface d’attaque réduite n’est pas une surface d’attaque nulle

Une image basée sur node:20-alpine contient typiquement 40 à 60 paquets. La même image basée sur node:20 (Debian full) en contient 500 à 800. Chaque paquet absent est un CVE potentiel en moins.

Mais attention : une image distroless qui n’a ni shell ni gestionnaire de paquets ne peut pas être inspectée facilement en production. Cela crée un faux sentiment de sécurité si le code qu’elle contient n’a jamais été analysé.

La règle : une image légère est un avantage sécuritaire seulement si elle embarque un code sain.


2. Les cinq principes fondamentaux

Principe 1 : Scanner tôt, scanner souvent

Le scan de vulnérabilités doit intervenir pendant le CI, pas après le déploiement.

# Exemple — GitHub Actions avec Trivy
- name: Scan de vulnérabilités
uses: aquasecurity/trivy-action@master
with:
image: mon-app:latest
severity: 'CRITICAL,HIGH'
exit-code: '1' # Fait échouer le build si vulnérabilité critique

Pourquoi Trivy et pas un autre ? Gratuit, open-source, rapide, couvre les CVE OS et les dépendances applicatives (npm, pip, Go modules). Il n’y a pas d’excuse pour ne pas l’intégrer.

Astuce temps réel : Activez le flag --ignore-unfixed pour ne bloquer le build que sur les vulnérabilités réellement corrigées en amont. Sinon, vous serez noyé dans des faux positifs que personne ne peut traiter.


Principe 2 : Le multi-stage build n’est pas optionnel

C’est le levier le plus puissant, et le plus sous-utilisé. Le principe est simple : séparer le monde de build du monde de runtime.

# Étape 1 — Build : tout est installé ici
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /app/server .
# Étape 2 — Runtime : image minimale, aucune toolchain
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /app/server /server
USER nonroot:nonroot
ENTRYPOINT ["/server"]

Ce pattern élimine automatiquement le compilateur, le gestionnaire de paquets, les headers de développement, et tous les outils qui n’ont rien à faire en production. Résultat : image de ~15 Mo au lieu de ~800 Mo, et zéro CVE de toolchain.


Principe 3 : Ne jamais exécuter en root

C’est la règle la plus simple et la plus violée. Une image qui tourne en root, même légère, peut compromettre l’hôte entier si une faille d’échappement existe.

# Option A — Utilisateur dédié (Alpine)
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
# Option B — Utilisateur intégré (Distroless)
USER nonroot:nonroot

Vérification rapide :

docker run --rm mon-app:latest id
# Doit afficher uid=65534(nonroot) — pas uid=0(root)

Si vous utilisez Kubernetes, ajoutez une securityContext pour rendre cela explicite et empêcher toute régression :

securityContext:
runAsNonRoot: true
runAsUser: 65534
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false


Principe 4 : Signer ses images (sans douleur)

La signature d’images garantit l’intégrité et la provenance. Avec cosign de Sigstore, c’est devenu triviale :

# Générer une paire de clés (une seule fois)
cosign generate-key-pair
# Signer l'image au moment du push
cosign sign --key cosign.key mon-registry.com/mon-app:v1.2.3
# Vérifier avant le déploiement
cosign verify --key cosign.pub mon-registry.com/mon-app:v1.2.3

Pour aller plus loin : intégrez cosign verify dans votre admission controller Kubernetes (Kyverno ou Gatekeeper). Résultat : aucune image non signée ne peut être déployée, point final.


Principe 5 : Réduire les secrets à zéro dans l’image

Les secrets dans les images Docker sont le péché originel du container security. Un docker history mon-app révèle chaque couche, y compris les secrets qui y ont été copiés — même s’ils ont été supprimés ensuite.

Ce qu’il ne faut JAMAIS faire :

# ❌ Catastrophe
COPY .env /app/.env
ENV DATABASE_URL=postgres://user:p4ss@host/db

Ce qu’il faut faire :

  • Injecter les secrets au runtime via des variables d’environnement (orchestrateur)
  • Utiliser un gestionnaire de secrets (Vault, AWS Secrets Manager, SOPS)
  • Scanner les images avec gitleaks ou trufflehog dans le CI pour détecter les fuites accidentelles

# Kubernetes — Injection propre
containers:
- name: app
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url


3. Le workflow en pratique : le pipeline sécurisé en 6 étapes

Étape Action Outil suggéré
1 Écrire un Dockerfile multi-stage Docker
2 Scanner l’image localement trivy image mon-app:dev
3 Scanner dans le CI Trivy / Grype (GitHub Actions)
4 Signer l’image Cosign + Sigstore
5 Vérifier la signature au déploiement Kyverno / Gatekeeper
6 Surveiller en production Falco / runtime scanning

Le tout, intégré sur 30 minutes un vendredi après-midi.


4. Ce qu’il faut éviter — Les fausses bonnes idées

Idée reçue Réalité
« Alpine est toujours plus sûr que Debian » Alpine utilise musl et busybox — certains outils de sécurité ou bibliothèques peuvent mal se comporter. Testez toujours.
« Distroless = invulnérable » Non. Cela supprime le bruit, pas les vulnérabilités du code applicatif ou des dépendances.
« Scanner une fois suffit » Les CVE sont publiées quotidiennement. Un scan il y a trois mois est un scan périmé.
« Les images officielles sont sûres » node:20 officiel contient régulièrement des CVE critiques. Officiel ne signifie pas sécurisé.


Conclusion

Sécuriser ses images légères n’est pas un projet — c’est une discipline. Les cinq principes ci-dessus (scanner, multi-stage, non-root, signer, pas de secrets) forment un socle suffisant pour 95% des cas d’usage.

Le piège est de chercher la perfection absolue : un pipeline de 15 étapes, un mesh de politiques impossible à maintenir, des outils que personne ne comprend. La sécurité durable est celle que les développeurs acceptent parce qu’elle ne les ralentit pas.

Commencez simple. Automatisez. Itérez.


Note : Les outils et versions mentionnés reflètent les pratiques courantes à ma date de connaissance (mai 2025). Les versions exactes et vulnérabilités peuvent avoir évolué — vérifiez toujours auprès des sources officielles.

Générateur de mots de passe gratuit
Calculatrice multifonction
Générez un code QR gratuitement
Créez votre lien de réservation public, gérez les disponibilités, le personnel et les rendez-vous.
Reste connecté partout avec la bonne eSIM, au bon prix.

Publications similaires