Aller au contenu principal
DockerSécuritéDevSecOps

Scanning et conformité Docker

30 min de lecture Apprendre Docker — Chapitre 10

Scanne tes images avec Trivy et Snyk, signe-les avec Docker Content Trust et audite ta config avec le CIS Benchmark.

Tu as construit tes images, sécurisé tes containers avec rootless et seccomp. Mais est-ce que tes images sont vraiment propres ? Une image Docker, c’est des centaines de paquets système empilés. Chacun peut embarquer une CVE critique sans que tu le saches.

Le scanning d’images et la conformité Docker, c’est le filet de sécurité qui attrape ce que tes yeux ne voient pas. Dans ce chapitre, tu vas apprendre à scanner tes images automatiquement, signer ce que tu déploies, et auditer ta configuration Docker contre les standards de l’industrie.

Pourquoi c’est important

Chaque semaine, des dizaines de nouvelles CVE sont publiées. Une image python:3.12-slim qui était propre lundi peut avoir deux vulnérabilités critiques vendredi. Sans scanning automatisé, tu déploies à l’aveugle.

🔥 Cas réel : En 2024, une entreprise SaaS a découvert que son image de production embarquait une version de libssl vulnérable à une RCE (Remote Code Execution) depuis 3 mois. Le fix existait — personne ne l’avait appliqué parce qu’aucun scan n’était en place. Résultat : breach, notification RGPD, et 6 semaines de remédiation.

Le scanning ne se limite pas aux CVE. Il couvre aussi :

  • Les secrets exposés — clés API, tokens oubliés dans une layer
  • Les mauvaises configurations — Dockerfile qui tourne en root, pas de healthcheck
  • La conformité — est-ce que ta config Docker respecte les standards CIS ?

💡 Tip DevOps : Le scan doit être automatique et bloquant. S’il ne casse pas ton pipeline quand il trouve un problème, il ne sert à rien.

Comprendre le scanning et la conformité

Le scanning Docker fonctionne sur trois axes complémentaires.

Le scan de vulnérabilités analyse chaque paquet de ton image (OS et applicatif) et le compare aux bases de CVE publiques (NVD, OSV, bases vendeurs). Trivy et Snyk sont les deux outils de référence — Trivy est open-source et rapide, Snyk ajoute du monitoring continu et des suggestions de remédiation.

La signature d’images garantit que l’image que tu pull est bien celle qui a été buildée. Docker Content Trust (DCT) utilise Notary pour signer cryptographiquement chaque tag. L’alternative moderne, Cosign (projet Sigstore), propose du “keyless signing” via OIDC — plus simple à intégrer en CI/CD.

L’audit de conformité vérifie ta configuration Docker globale contre le CIS Docker Benchmark, un référentiel de plus de 100 recommandations couvrant le host, le daemon, les images et le runtime.

🧠 À retenir : Scanner une image une seule fois au build ne suffit pas. Les CVE apparaissent après le déploiement. Il faut un scan continu sur tes images en production.

Commandes essentielles

Scanner une image avec Trivy — c’est la commande que tu utiliseras le plus. Elle analyse tous les paquets et remonte les vulnérabilités par sévérité :

# Installation de Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh

# Scan basique d'une image
trivy image python:3.12-slim

# Scan bloquant pour la CI — exit code 1 si CRITICAL ou HIGH
trivy image --severity CRITICAL,HIGH --exit-code 1 myapp:latest

# Scan complet : vulnérabilités + secrets + config
trivy fs --scanners vuln,secret,config ./

Intégrer Trivy dans GitHub Actions — pour que chaque PR soit scannée automatiquement avant merge :

# .github/workflows/security-scan.yml
name: Security Scan
on: [push, pull_request]

jobs:
  trivy-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build image
        run: docker build -t myapp:${{ github.sha }} .
      - name: Trivy scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          severity: 'CRITICAL,HIGH'
          exit-code: '1'
          format: 'sarif'
          output: 'trivy-results.sarif'
      - name: Upload to GitHub Security
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: 'trivy-results.sarif'

⚠️ Attention : Ne mets jamais --exit-code 0 en CI “pour que ça passe”. Si tu ignores les résultats, autant ne pas scanner.

Signer tes images avec Cosign — pour garantir l’intégrité de ce que tu déploies :

# Générer une paire de clés
cosign generate-key-pair

# Signer une image après le build
cosign sign --key cosign.key myregistry.com/myapp:v1.0

# Vérifier avant de déployer
cosign verify --key cosign.pub myregistry.com/myapp:v1.0

Auditer ta config avec Docker Bench Security — un audit automatisé basé sur le CIS Benchmark :

# Lancer l'audit CIS Docker Benchmark
docker run --rm --net host --pid host --userns host \
  --cap-add audit_control \
  -v /etc:/etc:ro \
  -v /var/lib:/var/lib:ro \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  --label docker_bench_security \
  docker/docker-bench-security

Configurer le daemon Docker selon les recommandations CIS :

{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "3" },
  "icc": false,
  "live-restore": true,
  "userland-proxy": false,
  "userns-remap": "default",
  "default-ulimits": {
    "nofile": { "Name": "nofile", "Hard": 64000, "Soft": 64000 }
  }
}

💡 Tip DevOps : "icc": false désactive la communication entre containers par défaut. Ça force l’utilisation de networks explicites — bien plus sécurisé qu’un réseau bridge ouvert.

Cas concret : sécuriser le pipeline d’une fintech

🔥 Cas réel : Une fintech déploie 15 microservices en containers. Voici comment elle a mis en place sa chaîne de scanning en 3 étapes.

Étape 1 — Scan au build. Chaque PR déclenche un trivy image --exit-code 1 --severity CRITICAL,HIGH. Les développeurs ne peuvent pas merger si une CVE critique est détectée. Un fichier .trivyignore permet d’accepter temporairement une CVE avec une date d’expiration et un ticket Jira associé.

Étape 2 — Signature au deploy. Après le merge sur main, la CI builde l’image, la scanne une dernière fois, puis la signe avec Cosign. Le cluster Kubernetes est configuré avec une admission policy qui refuse toute image non signée.

Étape 3 — Scan continu en production. Un cron Trivy rescanne toutes les images déployées chaque nuit. Si une nouvelle CVE critique apparaît sur une image en prod, une alerte Slack est envoyée à l’équipe avec le fix disponible.

Résultat : le temps moyen de remédiation d’une CVE critique est passé de 45 jours à 3 jours.

# Exemple de .trivyignore avec expiration
# CVE-2024-12345 — Pas exploitable (pas d'accès réseau externe) — JIRA-4567
CVE-2024-12345 exp:2026-04-15

# CVE-2024-67890 — Fix en attente upstream — JIRA-4890
CVE-2024-67890 exp:2026-05-01

🧠 À retenir : Le .trivyignore n’est pas une poubelle. Chaque exception doit avoir une justification, un ticket de suivi, et une date d’expiration.

Pièges fréquents

Scanner sans bloquer. Tu lances Trivy, tu vois 12 CVE critiques… et tu déploies quand même. Le scan doit être un gate bloquant dans ta CI, pas un rapport décoratif.

Ignorer les CVE “unfixable”. Certaines CVE n’ont pas encore de correctif. La bonne réponse n’est pas de les ignorer, mais de les accepter explicitement avec une justification et un suivi.

Ne scanner que l’image finale. Ton Dockerfile peut contenir des erreurs de configuration (run as root, pas de healthcheck) que le scan de vulnérabilités ne détecte pas. Utilise trivy config ./Dockerfile en complément.

Signer sans vérifier. Signer tes images c’est bien. Mais si personne ne vérifie la signature au moment du pull, ça ne sert à rien. Configure une policy d’admission côté orchestrateur.

⚠️ Attention : Ne monte jamais le socket Docker (-v /var/run/docker.sock) dans un container applicatif. C’est un accès root direct à l’hôte. Le Docker Bench Security le fera pour l’audit, mais c’est un outil d’administration, pas un service.

Utiliser latest en production. Sans tag versionné ou digest, tu ne peux pas savoir quelle version tourne réellement. Et la signature ne peut pas s’appliquer sur un tag mutable.

Exercice pratique

Objectif : Mettre en place un scan complet sur une image.

  1. Installe Trivy sur ta machine
  2. Scanne nginx:latest et note le nombre de CVE par sévérité
  3. Scanne nginx:alpine et compare — laquelle a le moins de vulnérabilités ?
  4. Crée un script scan.sh qui prend un nom d’image en argument et échoue si des CVE CRITICAL sont trouvées :
#!/bin/bash
IMAGE=${1:?Usage: ./scan.sh <image>}
echo "🔍 Scanning $IMAGE..."
trivy image --severity CRITICAL --exit-code 1 "$IMAGE"
if [ $? -eq 0 ]; then
  echo "✅ Aucune CVE critique trouvée"
else
  echo "❌ CVE critiques détectées — déploiement bloqué"
  exit 1
fi
  1. Bonus : Installe Cosign, génère une paire de clés, signe une image locale et vérifie la signature.

À retenir

🧠 Les 5 règles du scanning Docker :

  • Trivy en CI avec --exit-code 1 — chaque build est scanné, chaque CVE critique bloque le pipeline
  • Cosign pour signer — une image non signée ne devrait jamais atteindre la production
  • CIS Benchmark pour auditer — lance Docker Bench Security régulièrement, vise un score supérieur à 80%
  • Scan continu en prod — les CVE n’attendent pas ton prochain déploiement pour apparaître
  • .trivyignore documenté — chaque exception a une raison, un ticket, et une date d’expiration

La sécurité Docker, c’est de la défense en profondeur. Le scanning est une couche, pas la solution complète. Combine-le avec des images minimales, des builds multi-stage, un runtime restreint, et des secrets bien gérés.

🖥️ Pratique sur ton propre serveur

Pour suivre Apprendre Docker en conditions réelles, tu as besoin d'un VPS. DigitalOcean offre 200$ de crédit gratuit pour démarrer.

Obtenir 200$

Articles liés