DevSecOps

Sécurité Docker : les bases pour durcir les conteneurs en 2026

Sécurité Docker 2026 : hardening hôte, Dockerfile minimaliste, rootless, capabilities, seccomp, AppArmor, secrets, CIS Docker Benchmark, checklist complète.

Naim Aouaichia
13 min de lecture
  • Docker
  • Sécurité conteneurs
  • DevSecOps
  • Hardening
  • CIS Benchmark
  • Dockerfile
  • Seccomp
  • AppArmor
  • Runtime security

La sécurité Docker en 2026 repose sur une défense en profondeur à six couches : l'hôte Docker (rootless, user namespaces, kernel hardening), les images (base minimale, scan CVE, signing), le Dockerfile (multi-stage, pinning, USER non-root), le runtime (drop capabilities, seccomp, AppArmor, read-only rootfs), le réseau (VPC isolation, user-defined networks, pas de bridge default), et les secrets (BuildKit secrets, Vault, Docker Secrets). Le CIS Docker Benchmark v1.7 (117 contrôles) sert de checklist officielle, vérifiable automatiquement via Docker Bench Security ou Trivy compliance. Bien appliquées, ces bases réduisent de 70 à 90 % la surface d'attaque d'un conteneur classique et limitent l'impact d'une éventuelle évasion. Cet article couvre les six couches avec commandes concrètes, les pièges fréquents, et la checklist à appliquer sur un nouveau projet.

Threat model Docker : que défendre contre quoi

Avant les contrôles, comprendre les menaces principales.

MenaceImpactCouche défensive
Image compromise (CVE, backdoor)Code malveillant en prodScan, signing, base minimale
Secret exfiltré (ENV, layer, logs)Fuite credentials cloud/APIBuildKit secrets, Vault
Évasion de conteneur (privesc kernel)Accès hôte et pivotRootless, seccomp, AppArmor, user NS
Attaque réseau latéralePivot vers autres conteneursUser-defined networks, policies
Supply chain (pull image piégée)Image corrompue silencieusementDigest SHA256, cosign verify
Docker socket exposéPrivesc via API DockerRootless, firewall, never mount /var/run/docker.sock
Container escape via /proc ou mountAccès filesystem hôteNo --privileged, drop CAP_SYS_ADMIN

Couche 1 - Sécuriser l'hôte Docker

L'hôte Docker est le périmètre le plus critique. Une compromission hôte = compromission de tous les conteneurs.

Rootless mode (recommandé en 2026)

# Installation rootless Docker (utilisateur sans root)
curl -fsSL https://get.docker.com/rootless | sh
 
# Variables d'environnement à ajouter au shell
export PATH=$HOME/bin:$PATH
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock
 
# Vérifier le mode
docker info | grep -i rootless

En rootless, le daemon Docker et tous les conteneurs tournent sous l'utilisateur courant. Une évasion éventuelle n'atteint pas root sur l'hôte.

User namespaces (alternative si rootless impossible)

Si le rootless complet n'est pas faisable (contraintes d'entreprise, features avancées), activer User Namespace Remapping :

// /etc/docker/daemon.json
{
  "userns-remap": "default",
  "live-restore": true,
  "no-new-privileges": true,
  "icc": false,
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "3" }
}

Avec userns-remap, l'UID 0 dans le conteneur est mappé vers un UID non-privilégié sur l'hôte.

Hardening OS et kernel

OS de l'hôte :
  Mise à jour continue (unattended-upgrades Debian, dnf-automatic RHEL)
  Désactiver services inutiles
  Firewall restrictif (ufw, nftables, iptables)
  SSH : pas de password, key-only, port non-standard si exposé
 
Kernel :
  AppArmor (Ubuntu, Debian) ou SELinux (RHEL, Fedora) actif
  Filesystem /var/lib/docker sur volume chiffré (LUKS)
  Module kernel : désactiver ceux non utilisés

Couche 2 - Images : minimalisme et vérification

Base minimale

ubuntu:24.04                         : 77 MB, 90+ CVE résiduelles
python:3.12-slim                     : 45 MB, 20-40 CVE
python:3.12-alpine                   : 19 MB, 15-30 CVE
gcr.io/distroless/python3            : 25 MB, 0-5 CVE
cgr.dev/chainguard/python            : 15 MB, 0-3 CVE (sponsored)
scratch + binaire Go statique        : 5-15 MB, 0 CVE distro

Les images distroless (Google) et Chainguard Images éliminent shell, gestionnaire de paquets et outils système que 99 % des applications n'utilisent pas mais que les attaquants exploitent pour pivoter. Standard 2026 pour les équipes AppSec matures.

Vérification de provenance

# Pinning par digest SHA256 immuable (pas juste par tag)
docker pull python:3.12.6-slim@sha256:1a89c1d4...
 
# Vérification signature cosign keyless
cosign verify \
  --certificate-identity-regexp "https://github.com/org/.*" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  ghcr.io/org/app:sha-abc123

Scan automatique en CI

Voir le guide dédié scan de conteneurs : pourquoi et comment pour Trivy, Grype, Snyk, Docker Scout.

Couche 3 - Dockerfile sécurisé

Template Dockerfile minimaliste hardened 2026

# Stage 1 - build (gros, outils inclus)
FROM golang:1.22.3-alpine@sha256:d3d5b... AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /bin/app ./cmd/app
 
# Stage 2 - runtime (minimal, no shell, non-root)
FROM gcr.io/distroless/static-debian12:nonroot
USER 65532:65532
WORKDIR /app
COPY --from=build --chown=65532:65532 /bin/app /app/app
 
EXPOSE 8080
ENTRYPOINT ["/app/app"]

Règles Dockerfile essentielles

  1. Multi-stage builds systématiquement : exclure compilateurs et toolchain du runtime.
  2. USER non-root explicite (USER 10001 ou USER nonroot). Ne jamais laisser en root implicite.
  3. Pin par digest SHA256 sur les FROM, pas juste par tag (latest ou même 3.12-slim sont mutables).
  4. COPY plutôt que ADD sauf cas spécifique (ADD télécharge et extrait sans vérification).
  5. .dockerignore strict : exclure .git, .env, node_modules, clés SSH, tests.
  6. Pas de secret en ARG/ENV : utiliser BuildKit secrets ou mount temporaire.
  7. HEALTHCHECK défini pour l'observabilité.
  8. Flatten les layers peu utiles : RUN apt-get update && apt-get install -y ... && rm -rf /var/lib/apt/lists/* dans un seul RUN.
  9. EXPOSE documentaire uniquement : ne pas croire que c'est un contrôle de sécurité (c'est informatif).
  10. ENTRYPOINT plutôt que CMD pour contrôler strictement l'exécution.

BuildKit secrets - injection sûre au build

# syntax=docker/dockerfile:1.6
 
FROM alpine:3.19
RUN --mount=type=secret,id=github_token \
    TOKEN=$(cat /run/secrets/github_token) && \
    curl -H "Authorization: token $TOKEN" https://api.github.com/... -o /data.json
# Build avec secret injecté (non persisté dans layer)
DOCKER_BUILDKIT=1 docker build \
  --secret id=github_token,src=/path/to/token \
  -t my-app .

Le secret est accessible uniquement pendant l'exécution du RUN, jamais écrit dans une couche.

Couche 4 - Runtime : privilèges, capabilities, seccomp

Minimum privilege au lancement

docker run \
  --read-only \                          # rootfs en lecture seule
  --tmpfs /tmp:rw,size=64M,noexec \      # /tmp isolé
  --user 10001:10001 \                   # non-root
  --cap-drop=ALL \                       # drop toutes les capabilities
  --cap-add=NET_BIND_SERVICE \           # réajouter ce qui est strictement nécessaire
  --security-opt=no-new-privileges \     # pas d'escalade via setuid
  --security-opt=seccomp=profile.json \  # profile seccomp custom
  --security-opt=apparmor=app-profile \  # profile AppArmor
  --pids-limit=100 \                     # limite PID pour éviter fork bomb
  --memory=512m --memory-swap=512m \     # limite RAM
  --cpus=1.0 \                           # limite CPU
  --network=my-app-net \                 # pas le bridge default
  my-app:1.2.3@sha256:abc...

Linux capabilities : 38 à comprendre

Capabilities dangereuses à DROP absolument :
  CAP_SYS_ADMIN         : « root-lite », très puissant
  CAP_SYS_MODULE        : chargement modules kernel
  CAP_SYS_PTRACE        : debug et injection processus
  CAP_SYS_RAWIO         : accès matériel brut
  CAP_NET_ADMIN         : configuration réseau
  CAP_SYS_BOOT          : reboot
  CAP_DAC_READ_SEARCH   : lecture contournant les permissions
  CAP_SETUID / SETGID   : changement d'UID/GID
 
Capabilities souvent nécessaires à ajouter :
  CAP_NET_BIND_SERVICE  : écouter sur port inférieur à 1024
  CAP_CHOWN             : chown dans le conteneur
  CAP_SETGID / SETUID   : si l'app change d'UID explicitement

Pratique : --cap-drop=ALL puis --cap-add=NET_BIND_SERVICE (ou autre capability précise) pour ce qui est strictement nécessaire. Par défaut, Docker drop déjà 22 capabilities, mais garde 14 qui peuvent être exploitées.

Seccomp - filtre syscalls

Docker applique un profil seccomp par défaut qui bloque environ 44 appels système dangereux (reboot, mount, keyctl, kexec_load, personality, etc.).

# Voir le profil seccomp par défaut
docker run --rm alpine cat /proc/1/status | grep Seccomp
 
# Profil custom : autoriser uniquement les syscalls nécessaires
docker run --security-opt=seccomp=/path/to/my-profile.json my-app

Un profil seccomp custom bien taillé réduit la surface de 300+ syscalls à 50-100 selon l'application. Outils pour générer : falco avec syscall tracing, strace en mode record, Docker seccomp-profile generator.

AppArmor ou SELinux

AppArmor (Ubuntu, Debian) et SELinux (RHEL, Fedora) appliquent des politiques MAC (Mandatory Access Control) sur les ressources accessibles.

# AppArmor - appliquer un profile custom
docker run --security-opt=apparmor=my-app-profile my-app
 
# Voir le profile par défaut Docker
cat /etc/apparmor.d/docker-default

Un profile AppArmor dédié à une application verrouille les chemins filesystem accessibles, les sockets, les modes d'ouverture, etc. Effort initial non trivial (2-4 heures par application), gain significatif en défense en profondeur.

Read-only root filesystem

docker run --read-only --tmpfs /tmp:rw,size=64M my-app

Empêche un attaquant qui compromet l'application d'écrire des binaires malveillants ou de modifier la configuration. Certaines apps demandent /tmp writable, à monter séparément en tmpfs.

Couche 5 - Réseau Docker

Ne pas utiliser le bridge default

Le réseau bridge par défaut permet à tous les conteneurs de communiquer entre eux. Créer des réseaux user-defined isolés :

# Créer un réseau dédié
docker network create --driver=bridge my-app-net
 
# Lancer les conteneurs dans ce réseau
docker run --network=my-app-net --name=api my-api:1.0
docker run --network=my-app-net --name=db my-db:1.0

Les conteneurs sur des réseaux user-defined séparés ne se voient pas.

Pas de publication de port inutile

# Mauvais - publication sur toutes les interfaces
docker run -p 5432:5432 postgres  # écoute 0.0.0.0:5432, exposé Internet
 
# Meilleur - binding localhost seulement
docker run -p 127.0.0.1:5432:5432 postgres
 
# Encore mieux - pas de publication, accès via réseau user-defined
docker run --network=my-app-net --name=db postgres

Protéger Docker socket

Ne JAMAIS :
  Monter /var/run/docker.sock dans un conteneur exposé (Traefik, Portainer
  exposés Internet) - équivaut à root sur l'hôte pour l'attaquant.
 
Alternatives :
  Podman socket rootless
  Docker Socket Proxy (Tecnativa) pour exposer une API restreinte
  Traefik avec socket read-only + mode file plutôt que dynamic

Couche 6 - Gestion des secrets

Hiérarchie des approches par maturité

À éviter :
  Secret dans le Dockerfile (ARG ou ENV)     → fuit via docker history
  Secret dans docker run -e SECRET=...        → fuit via docker inspect + logs
  Secret en clair dans un volume monté        → fuit si volume exposé
 
Acceptable pour dev local :
  Fichier .env chargé via docker run --env-file
  Secret dans Docker Desktop Secrets
 
Recommandé pour production :
  Docker Secrets (Swarm uniquement)
  Kubernetes Secrets (avec encryption at rest etcd + Sealed Secrets)
  HashiCorp Vault (sidecar injector ou Vault Agent)
  Cloud-native : AWS Secrets Manager, GCP Secret Manager, Azure Key Vault
  OIDC Workload Identity Federation pour CI/CD (sans secret du tout)

Exemple Kubernetes Sealed Secret (chiffrement à la source)

# Générer un Sealed Secret chiffré avec la clé publique du cluster
echo -n "my-super-secret-value" | kubectl create secret generic my-secret \
  --dry-run=client --from-file=db-password=/dev/stdin -o yaml | \
  kubeseal --format yaml > sealed-secret.yaml
 
# Le fichier sealed-secret.yaml est commitable dans Git, chiffré.
# Le cluster a la clé privée pour le déchiffrer.

CIS Docker Benchmark et vérification automatique

Le CIS Docker Benchmark v1.7 (2024) couvre 117 contrôles répartis en 7 sections :

1. Host Configuration              (~20 contrôles)
2. Docker Daemon Configuration     (~35 contrôles)
3. Docker Daemon Files             (~15 contrôles)
4. Container Images and Build File (~12 contrôles)
5. Container Runtime               (~30 contrôles)
6. Docker Security Operations      (~2 contrôles)
7. Docker Swarm Configuration       (~9 contrôles)

Vérification automatique

# Docker Bench Security (script officiel, 117 checks)
docker run --rm --net host --pid host --userns host --cap-add audit_control \
  -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
  -v /etc:/etc:ro \
  -v /usr/bin/containerd:/usr/bin/containerd:ro \
  -v /usr/bin/runc:/usr/bin/runc:ro \
  -v /usr/lib/systemd:/usr/lib/systemd: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
 
# Alternative : Trivy compliance CIS
trivy image --compliance docker-cis my-app:1.0
 
# Alternative : Prowler multi-cloud
prowler -c cis_docker

Objectif pragmatique : atteindre 80-90 % de conformité. 100 % est souvent irréaliste car certains contrôles cassent des fonctionnalités légitimes.

Docker Desktop en 2026 : Enhanced Container Isolation

Docker Desktop (Mac, Windows, Linux) est utilisé massivement par les développeurs. Risques spécifiques : il tourne avec privilèges élevés sur le poste de travail, expose l'API Docker localement.

Depuis 2023, Docker Desktop Business propose Enhanced Container Isolation (ECI) basé sur Sysbox :

  • Les conteneurs deviennent automatiquement rootless côté hôte.
  • Protection contre les évasions de conteneur même pour des images non-root.
  • Blocage des opérations privilégiées dangereuses (mount /, accès à Docker socket interne, etc.).

Pour un développeur en 2026, l'alternative complète : Podman Desktop (rootless natif, gratuit, compatible API Docker), Rancher Desktop, ou Colima sur Mac.

Checklist développeur avant production

Image et build :
  [ ] Image de base minimale (distroless, Chainguard ou Alpine pinné)
  [ ] FROM avec digest SHA256 immuable
  [ ] Multi-stage build avec runtime stripped
  [ ] USER non-root explicite dans Dockerfile
  [ ] .dockerignore complet (.git, .env, node_modules, tests)
  [ ] Pas de secret dans ARG ou ENV
  [ ] HEALTHCHECK défini
 
Runtime :
  [ ] --cap-drop=ALL + --cap-add explicites
  [ ] --security-opt=no-new-privileges
  [ ] --read-only + --tmpfs /tmp
  [ ] --pids-limit, --memory, --cpus définis
  [ ] Seccomp custom pour applications à fort volume d'utilisateurs
  [ ] AppArmor ou SELinux profile dédié
 
Hôte :
  [ ] Rootless Docker ou user namespaces activé
  [ ] daemon.json hardened (no-new-privileges, live-restore, icc:false)
  [ ] Docker Bench Security > 80 % pass
  [ ] OS hardened (AppArmor/SELinux, firewall)
 
Secrets :
  [ ] Aucun secret dans l'image
  [ ] Docker Secrets, Vault ou Cloud secret service utilisé
  [ ] BuildKit secrets pour les builds nécessitant credentials
 
Réseau :
  [ ] Pas de bridge default, réseaux user-defined
  [ ] Pas de docker.sock monté dans un conteneur exposé
  [ ] Binding 127.0.0.1 pour services non publics
  [ ] TLS sur l'API Docker si exposée (rare, déconseillé)
 
Observabilité :
  [ ] Logs conteneurs remontés dans un SIEM
  [ ] Détection runtime (Falco, Tetragon) si criticité élevée

Points clés à retenir

  • Sécurité Docker = défense en profondeur à 6 couches : hôte, images, Dockerfile, runtime, réseau, secrets. Aucune couche ne suffit seule.
  • 4 actions prioritaires débutant : rootless mode, image distroless/Chainguard, USER non-root, secrets hors ENV/ARG. Couvre 70 % du risque.
  • Runtime hardening essentiel : --cap-drop=ALL + --cap-add ciblé + --read-only + --security-opt=no-new-privileges. Seccomp custom et AppArmor pour criticité élevée.
  • CIS Docker Benchmark v1.7 = 117 contrôles officiels. Vérifier via Docker Bench Security, Trivy compliance, Prowler. Viser 80-90 %.
  • Secrets : jamais en ENV/ARG dans Dockerfile. BuildKit --mount=type=secret au build, Vault/Secret Manager/Kubernetes Secrets en runtime. OIDC WIF pour CI/CD idéalement.
  • Docker Desktop Business propose Enhanced Container Isolation (Sysbox). Alternatives OSS : Podman Desktop, Rancher Desktop, Colima.
  • Ne jamais monter /var/run/docker.sock dans un conteneur exposé : c'est root sur l'hôte pour tout attaquant qui le compromet.

Pour compléter le durcissement par la détection des vulnérabilités dans les images et le scan continu du registry, voir scan de conteneurs : pourquoi et comment. Pour resituer Docker security dans une discipline DevSecOps complète avec pipelines CI/CD shift-left, lire différence entre DevOps et DevSecOps. Pour la progression carrière et l'apprentissage structuré, la roadmap DevSecOps 2026 détaille les 4 étapes.

Questions fréquentes

  • Par où commencer pour sécuriser Docker quand on débute ?
    Quatre actions prioritaires dans l'ordre : passer l'hôte en rootless mode ou en non-root, utiliser une image de base minimale (distroless, Chainguard, Alpine), ne jamais tourner les conteneurs en root (`USER 10001` dans Dockerfile), et sortir les secrets des variables d'environnement vers Docker Secrets ou Vault. Ces quatre mesures suppriment 70 % des risques Docker en 2026. Ensuite seulement aborder seccomp, AppArmor, capabilities et read-only rootfs.
  • Est-ce que rootless Docker est prêt pour la production en 2026 ?
    Oui, rootless Docker est stable depuis Docker Engine 20.10 (2020) et largement adopté en 2026. Il tourne le daemon et les conteneurs sous un utilisateur non-privilégié, limitant drastiquement l'impact d'une évasion de conteneur. Limitations résiduelles : certaines fonctionnalités réseau (low ports, réseaux avancés overlay multi-host sans workaround), certaines opérations privilégiées. Alternative progressive : user namespaces + Podman (rootless natif, API Docker compatible).
  • Quelle différence entre capabilities, seccomp et AppArmor ?
    Les trois couches se complètent. Linux capabilities fractionnent les privilèges root en 38 capacités individuelles (CAP_NET_BIND_SERVICE, CAP_SYS_ADMIN, etc.) : Docker drop 22 par défaut sur un conteneur non-root. Seccomp filtre les appels système autorisés : le profil Docker par défaut bloque 44 syscalls dangereux. AppArmor (ou SELinux) applique des politiques MAC (Mandatory Access Control) sur les fichiers et ressources accessibles. Pour un hardening fort en production : drop ALL capabilities + `--cap-add` explicites + seccomp custom + AppArmor profile dédié.
  • Comment éviter les secrets dans les images Docker ?
    Trois règles cumulatives. 1) Jamais de secret dans Dockerfile via ARG ou ENV (persistés dans layer, visibles par docker history). 2) Utiliser BuildKit secrets via `--mount=type=secret` pour les builds multi-stage. 3) En runtime, injecter via Docker Secrets (Swarm), Kubernetes Secrets en cluster, HashiCorp Vault pour production exigeante, ou des services cloud (Secret Manager GCP, Secrets Manager AWS, Key Vault Azure). Ne jamais se contenter de variables d'environnement brutes : elles fuient via logs, métriques, docker inspect.
  • CIS Docker Benchmark, qu'est-ce que c'est et comment le vérifier ?
    Le CIS Docker Benchmark est un référentiel de 117 contrôles de hardening publié par le Center for Internet Security. Il couvre l'hôte Docker, le daemon, les images, les conteneurs, et Docker Swarm. Version 1.7 en vigueur en 2026, alignée avec Docker Engine 24.x. Pour le vérifier automatiquement : `docker/docker-bench-security` (script bash OSS), ou intégré dans Trivy (`trivy image --compliance docker-cis`), Prowler, Wiz. Objectif réaliste : 80 %+ de conformité. 100 % est difficile car certains contrôles cassent des use cases légitimes.
  • Docker Desktop est-il sûr pour la production ?
    Docker Desktop est conçu pour le développement local, pas la production. Pour la production : Docker Engine CE sur Linux, Podman, ou un orchestrateur (Kubernetes, Docker Swarm, Nomad). Docker Desktop a introduit en 2023 Enhanced Container Isolation (ECI) via Sysbox pour durcir l'isolation des conteneurs sur les postes devs. En 2026, Docker Desktop Business (commercial) est souvent imposé en entreprise pour la conformité licence, alors que les alternatives Podman Desktop, Rancher Desktop et Colima restent gratuites et suffisantes.

Écrit par

Naim Aouaichia

Expert cybersécurité et fondateur de Zeroday Cyber Academy

Expert cybersécurité avec un master spécialisé et un parcours hybride : développement, DevOps, DevSecOps, SOC, GRC. Fondateur de Hash24Security et Zeroday Cyber Academy. Formateur et créateur de contenu technique sur la cybersécurité appliquée, la sécurité des LLM et le DevSecOps.