Docker Hardened Images : la sécurité des conteneurs repensée
Docker a lancé en 2026 le programme ‘Docker Hardened Images’ (DHI) — une collection d’images officielles prédurcies, auditées par des équipes de sécurité, et fournies avec des attestations de provenance (SLSA Level 3). Ces images sont disponibles dans Docker Hub et constituent le nouveau standard de référence pour les images de base en production.
Avant DHI, choisir une image de base sécurisée nécessitait de naviguer entre des options imparfaites : les images officielles Docker Hub (souvent volumineuses avec des packages inutiles), les images Alpine (légères mais avec des incompatibilités libc), et les images distroless de Google (sécurisées mais difficiles à déboguer). DHI consolide les meilleures pratiques de chacune dans une gamme cohérente.
Ce guide couvre l’utilisation des Docker Hardened Images, les techniques de durcissement de vos propres Dockerfiles, l’intégration de Docker Scout pour le scan de vulnérabilités, et les politiques d’images à implémenter pour les environnements de production.
Anatomie d’une image Docker sécurisée
Une image Docker sécurisée repose sur quatre principes. Minimalité : n’inclure que les packages strictement nécessaires à l’exécution de l’application. Une image Python qui fait tourner une API REST n’a pas besoin d’un shell bash, de curl, ou de compilateurs — les images distroless ou DHI les excluent par défaut.
Utilisateur non-root : l’application s’exécute sous un utilisateur dédié avec des privilèges minimaux. Si un attaquant exploite une vulnérabilité dans l’application, il obtient les droits de cet utilisateur restreint, pas de root. Configurez toujours un `USER appuser` dans votre Dockerfile avant l’instruction `CMD`.
Filesystem en lecture seule : le container ne peut pas modifier son filesystem runtime (sauf les volumes explicitement montés). Cela prévient de nombreuses attaques qui nécessitent d’écrire des fichiers sur le disque (scripts de persistence, shells dropped). Configurez `securityContext.readOnlyRootFilesystem: true` dans votre manifeste Kubernetes.
Multi-stage builds : réduire la surface d’attaque
Le multi-stage build est la technique la plus efficace pour réduire la taille et la surface d’attaque des images de production. Le principe : utiliser une image complète (avec compilateurs, outils de build) pour construire l’application, puis copier UNIQUEMENT les artefacts de build dans une image minimale pour la production.
Pour une application Python, le stage de build installe les dépendances et compile les wheels. Le stage de production utilise une image Python distroless ou DHI, copie les wheels et le code source, et ne contient aucun outil d’installation. Résultat : une image de production 5 à 10 fois plus petite, sans pip, sans gcc, sans bash.
Pour les applications Go, le multi-stage est encore plus radical : le binaire compilé (statically linked) peut être copié dans `FROM scratch` — une image absolument vide. Le container résultant ne contient que votre binaire et rien d’autre. Aucun shell, aucune libc, aucune surface d’attaque au niveau OS.
Docker Scout : scan de vulnérabilités et CVEs
Docker Scout est l’outil de scan de vulnérabilités intégré à Docker Desktop et Docker Hub. Il analyse l’image layer par layer, identifie tous les packages installés, et les compare avec des bases de CVEs (NVD, GitHub Advisory, OSS-Fuzz). Disponible gratuitement pour les repositories publics et en tier payant pour les private registries.
Intégrez Docker Scout dans votre CI/CD : `docker scout cves monimage:tag –exit-code` retourne un code non-zéro si des CVEs critiques ou élevées sont détectées. Cela bloque automatiquement le push d’une image vulnérable vers votre registry de production. Configurez des exceptions pour les CVEs sans patch disponible (avec une justification documentée et une date de révision).
Au-delà des CVEs, Docker Scout analyse les politiques de sécurité configurées (pas d’image root, pas de latest tag, provenance attestation présente) et vous donne un score de conformité. Ce score peut être intégré dans des gates de déploiement : une image en dessous d’un score minimum est bloquée par ArgoCD ou votre pipeline CI.
Politiques d’images en production : OPA et Kyverno
Une politique d’images cohérente et automatiquement enforçée est la clé de la sécurité des conteneurs en production. Des outils comme Kyverno (natif Kubernetes, YAML) ou OPA Gatekeeper permettent de définir des règles qui bloquent le déploiement de pods qui ne respectent pas vos standards.
Règles Kyverno essentielles : interdire les images avec le tag `:latest` (oblige des tags de version immuables), interdire les conteneurs qui s’exécutent en root (uid 0), interdire les conteneurs en mode privilégié (`privileged: true`), et interdire les images provenant de registries non approuvés (seuls votre registry interne et Docker Hub DHI sont autorisés).
Ces politiques s’appliquent en mode audit (log seulement) ou enforce (bloque le pod). Commencez en mode audit pour identifier les violations existantes sans casser la production, corriger les violations, puis passez en enforce. La transition audit → enforce sur un cluster existant prend typiquement 2 à 4 semaines.
Gestion du cycle de vie des images et mise à jour
Les images Docker ont un cycle de vie : une image sécurisée aujourd’hui peut contenir des CVEs demain suite à la découverte de nouvelles vulnérabilités dans ses composants. Sans processus de mise à jour des images de base, votre sécurité se dégrade silencieusement.
Automatisez la mise à jour des images de base avec Renovate Bot ou Dependabot. Ces outils détectent les nouvelles versions de vos images FROM (ex: `python:3.12-slim → python:3.13-slim`) et créent automatiquement des pull requests. Configurez un cycle de mise à jour hebdomadaire pour les images de base — les vulnérabilités critiques dans les images populaires sont patchées rapidement.
Implémentez une politique de rétention des images dans votre registry : supprimez les images non déployées après 30 jours, et les images en production après 90 jours de non-utilisation. Un registry non entretenu accumule des milliers d’images obsolètes, augmentant les coûts de stockage et compliquant l’audit de sécurité. Harbour, Artifactory, et AWS ECR proposent tous des politiques de lifecycle automatisées.
# Dockerfile sécurisé avec multi-stage build
# ─── Stage 1 : Build ───────────────────────────────────────────────
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
# Installer dans un venv isolé (pas de pollution de l'image base)
RUN python -m venv /opt/venv && /opt/venv/bin/pip install --no-cache-dir --upgrade pip && /opt/venv/bin/pip install --no-cache-dir -r requirements.txt
# ─── Stage 2 : Production (Docker Hardened Image) ──────────────────
FROM python:3.12-slim AS production
# Métadonnées et provenance
LABEL org.opencontainers.image.source="https://github.com/monorg/monapp"
LABEL org.opencontainers.image.vendor="MonOrg"
# Utilisateur non-root dédié
RUN groupadd -r appgroup && useradd -r -g appgroup -u 1000 appuser
WORKDIR /app
# Copier UNIQUEMENT le venv et le code source (pas pip, pas compilateurs)
COPY --from=builder /opt/venv /opt/venv
COPY --chown=appuser:appgroup src/ ./src/
# Droits minimaux sur les fichiers
RUN chmod -R 550 /app && chmod -R 550 /opt/venv
USER appuser
ENV PATH="/opt/venv/bin:$PATH"
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
EXPOSE 8080
# Healthcheck intégré
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8080/health')" || exit 1
CMD ["python", "-m", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8080"]
# Pour Kubernetes, ajoutez dans le securityContext du pod :
# securityContext:
# readOnlyRootFilesystem: true
# allowPrivilegeEscalation: false
# runAsNonRoot: true
# runAsUser: 1000
Commentaires (0)
Laisser un commentaire
Les commentaires sont modérés. Questions WordPress, cybersécurité ou dev web bienvenues.