E-NO
DevOps 14 min de lecture

Sécurité Docker en production : liste de contrôle pratique avec exemples

calendar_today Publié : 2026-11-01
update Dernière mise à jour : 2026-11-01
analytics Efficacité SEO : 97%
Illustration du guide technique pour « Sécurité Docker en production : liste de contrôle pratique avec exemples ».

Introduction

Utiliser Docker en production ne se limite pas à construire et expédier des images. La sécurité est une responsabilité opérationnelle continue qui englobe la configuration, la surveillance, la maintenance, les sauvegardes et les mises à niveau. Sans processus reproductible, les équipes s'exposent à des risques d'évasion de conteneur, d'élévation de privilèges, de fuite de secrets et d'attaques de la chaîne d'approvisionnement.

Cet article fournit une liste de contrôle opérationnelle pratique pour la sécurité Docker en production. Chaque section inclut des commandes concrètes, des extraits de configuration, des sorties attendues et des étapes de vérification. L'objectif est de donner aux développeurs, consultants DevOps et équipes techniques de startups une référence adaptable à leurs propres environnements.

Nous couvrons :

  • L'inventaire des versions Docker et les prérequis d'environnement
  • L'application d'un chemin de configuration sûr avec un durcissement ciblé
  • La vérification de la posture de sécurité avec des contrôles observables
  • La gestion des modes de défaillance et les procédures de récupération
  • Une liste de contrôle opérationnelle reproductible pour une sécurité continue

À la fin, vous disposerez d'un ensemble clair d'actions pour durcir les hôtes Docker, appliquer des politiques d'exécution, détecter les anomalies et récupérer après incident.

Inventaire des versions et de l'environnement

Avant toute modification de sécurité, documentez l'environnement Docker actuel. Cela inclut les versions du moteur Docker et de la CLI, le runtime de conteneur, le système d'exploitation hôte, les pilotes de stockage et de réseau, ainsi que les paramètres actuels liés à la sécurité.

Vérifier les versions Docker

Exécutez la commande suivante sur chaque hôte Docker :

docker version

Exemple de sortie (tronquée) :

Client: Docker Engine - Community
  Version:           24.0.5
  API version:       1.43
  Go version:        go1.20.4
  Git commit:        ced0996
  Built:             Fri Jul 21 19:01:22 2023
  OS/Arch:           linux/amd64
  Context:           default

Server: Docker Engine - Community
  Engine:
    Version:          24.0.5
    API version:      1.43 (minimum version 1.12)
    Go version:       go1.20.4
    Git commit:       a61e2b4
    Built:            Fri Jul 21 19:01:22 2023
    OS/Arch:          linux/amd64
    Experimental:     false
  containerd:
    Version:          1.6.21
    GitCommit:        3dce8eb055cbb6878b1e53c1b34f8f1b3e3f0c1a
  runc:
    Version:          1.1.7
    GitCommit:        v1.1.7-0-g860f061
  docker-init:
    Version:          0.19.0
    GitCommit:        de40ad0

Notez la version du moteur et les composants (containerd, runc). Les correctifs de sécurité ciblent souvent des versions spécifiques, donc maintenir cet inventaire à jour est essentiel.

Inspecter la configuration de sécurité actuelle

Utilisez docker info pour voir les paramètres de sécurité généraux :

docker info --format '{{json .SecurityOptions}}'

Exemple de sortie :

["name=seccomp,profile=builtin","name=cgroupns"]

Si vous voyez name=userns dans la sortie, le remappage des espaces de noms utilisateur est activé. Sinon, il peut être candidat à un durcissement (discuté plus loin).

Vérifiez également le profil seccomp par défaut et le statut d'AppArmor/SELinux :

docker info | grep -E 'Security Options|Kernel Version|Operating System'

Identifier les conteneurs privilégiés

Listez les conteneurs en cours d'exécution et vérifiez le mode privilégié :

docker ps --quiet | xargs docker inspect --format '{{.Name}}: Privileged={{.HostConfig.Privileged}}'

Exemple de sortie :

/mysql: Privileged=false
/web: Privileged=true
/cache: Privileged=false

Le conteneur /web s'exécute en mode privilégié, ce qui est risqué. Vous traiterez cela dans le chemin de configuration sûr.

Prérequis

Assurez-vous d'avoir :

  • Accès SSH aux hôtes Docker avec sudo (ou équivalent)
  • Un environnement de test ou de préproduction pour valider les changements avant la production
  • Sauvegarde de la configuration du démon Docker (/etc/docker/daemon.json)
  • Sauvegarde des fichiers d'unité systemd ou scripts d'init pour Docker
  • Capacité à redémarrer le démon Docker (nécessite une fenêtre de maintenance planifiée)
  • Outils d'agrégation de journaux et de surveillance (par exemple, ELK, Prometheus, Datadog)

Documentez l'inventaire dans un tableur ou une base de données de gestion de configuration. Cette base sera utilisée pour la vérification ultérieure.

Question rapide 1 sur 2

Selon le passage sur la plateforme Docker, qu'est-ce que Docker permet de faire ?

Le passage indique que Docker permet d'empaqueter et d'exécuter une application dans un environnement faiblement isolé appelé conteneur, et que l'isolation et la sécurité permettent d'exécuter de nombreux conteneurs simultanément sur un hôte.

Chemin de configuration sûr

Appliquez le durcissement de sécurité de manière contrôlée et incrémentale. Commencez par les changements à plus faible risque et plus fort impact : configuration du démon, paramètres d'exécution des conteneurs et politiques réseau. Testez toujours sur un hôte hors production d'abord.

1. Durcir le démon Docker

Le démon Docker s'exécute avec les privilèges root et contrôle tous les conteneurs. Un démon mal configuré peut exposer l'hôte. Modifiez /etc/docker/daemon.json (créez-le s'il n'existe pas) et ajoutez ou modifiez ce qui suit :

{
  "icc": false,
  "log-level": "info",
  "userland-proxy": false,
  "no-new-privileges": true,
  "live-restore": true,
  "iptables": true,
  "ip6tables": true,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 64000,
      "Soft": 64000
    }
  }
}

Paramètres clés :

  • "icc": false : Désactive la communication inter-conteneurs par défaut. Les conteneurs doivent être explicitement liés ou sur le même réseau défini par l'utilisateur pour communiquer.
  • "no-new-privileges": true : Empêche les conteneurs d'obtenir des privilèges supplémentaires via les binaires setuid/setgid ou d'autres mécanismes.
  • "live-restore": true : Maintient les conteneurs en cours d'exécution lorsque le démon Docker est arrêté, réduisant les temps d'arrêt lors des mises à niveau.

Après modification, redémarrez le démon Docker :

sudo systemctl restart docker

Vérifiez les paramètres :

docker info --format '{{json .SecurityOptions}}'

La sortie attendue devrait inclure no-new-privileges. En fait, no-new-privileges est un drapeau par conteneur ; le paramètre du démon n'y est pas affiché. Vérifiez plutôt docker info pour les paramètres au niveau du démon :

sudo docker info | grep -i 'Default Runtime\|Cgroup Driver\|Security Options'

Mais pour vérifier icc: false, exécutez :

docker network inspect bridge | grep -i 'com.docker.network.bridge.enable_icc'

Sortie attendue :

"com.docker.network.bridge.enable_icc": "false"

2. Activer le remappage des espaces de noms utilisateur

Les espaces de noms utilisateur mappent l'utilisateur root du conteneur vers un utilisateur non root sur l'hôte, limitant l'impact des évasions de conteneur. C'est un contrôle de sécurité puissant mais peut casser certaines charges de travail (par exemple, celles nécessitant des permissions de fichiers spécifiques). Testez minutieusement.

Pour l'activer, ajoutez à /etc/docker/daemon.json :

{
  "userns-remap": "default"
}

Puis redémarrez Docker :

sudo systemctl restart docker

Vérifiez que l'utilisateur remappé existe :

id dockremap

Exemple de sortie :

uid=140000(dockremap) gid=140000(dockremap) groups=140000(dockremap)

Remarque : Si vous avez des conteneurs ou volumes existants, ils peuvent avoir des problèmes de permission après activation. Prévoyez de recréer les conteneurs et d'ajuster la propriété des volumes. Référez-vous à la documentation Docker pour les étapes de migration.

3. Restreindre les capacités des conteneurs

Par défaut, les conteneurs Docker reçoivent un sous-ensemble de capacités Linux. Vous pouvez réduire davantage les privilèges en supprimant toutes les capacités et en n'ajoutant que celles nécessaires. Utilisez les drapeaux --cap-drop et --cap-add.

Exemple : Exécuter un conteneur Nginx avec des capacités minimales :

docker run -d --name web \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  --security-opt no-new-privileges \
  nginx:alpine

Ici, nous supprimons toutes les capacités, puis ajoutons uniquement NET_BIND_SERVICE (pour se lier au port 80). Nous définissons également no-new-privileges pour empêcher l'élévation de privilèges.

Vérifiez les capacités d'un conteneur en cours d'exécution :

docker inspect --format '{{.HostConfig.CapAdd}} {{.HostConfig.CapDrop}}' web

Sortie attendue :

[NET_BIND_SERVICE] [ALL]

4. Appliquer des limites de ressources

Une utilisation illimitée des ressources peut conduire à un déni de service. Définissez des limites de mémoire et de CPU sur les conteneurs :

docker run -d --name api \
  --memory 512m \
  --cpus 1.5 \
  --pids-limit 100 \
  myapp:1.0

Ces drapeaux garantissent que le conteneur utilise au maximum 512 Mo de RAM, 1,5 cœur CPU et 100 processus/threads. --pids-limit empêche les bombes fork.

Vérifiez les limites :

docker inspect --format '{{.HostConfig.Memory}} {{.HostConfig.NanoCpus}} {{.HostConfig.PidsLimit}}' api

Sortie attendue :

536870912 1500000000 100

5. Utiliser un système de fichiers racine en lecture seule

De nombreuses applications peuvent fonctionner avec un système de fichiers racine en lecture seule, empêchant les attaquants d'écrire des fichiers malveillants. Utilisez --read-only et montez des volumes inscriptibles pour des chemins spécifiques (par exemple, /tmp, /var/run).

docker run -d --name web \
  --read-only \
  --tmpfs /tmp \
  --tmpfs /var/run \
  nginx:alpine

Vérifiez :

docker inspect --format '{{.HostConfig.ReadonlyRootfs}}' web

Sortie attendue :

true

6. Sécuriser la socket Docker

La socket Docker (/var/run/docker.sock) accorde un contrôle total sur le démon. Ne l'exposez jamais aux conteneurs sauf nécessité absolue. Si un conteneur doit gérer Docker (par exemple, Portainer), utilisez un proxy comme docker-socket-proxy avec des permissions restreintes.

Vérifiez si un conteneur monte la socket :

docker ps --quiet | xargs docker inspect --format '{{.Name}}: {{range .Mounts}}{{if eq .Source "/var/run/docker.sock"}}YES{{end}}{{end}}'

Si un conteneur affiche YES, évaluez s'il a réellement besoin de la socket et restreignez avec un proxy.

7. Segmentation du réseau

Utilisez des réseaux bridge définis par l'utilisateur pour isoler les conteneurs. Évitez d'utiliser le réseau bridge par défaut en production.

Créez un réseau :

docker network create --driver bridge frontend

Exécutez des conteneurs attachés à ce réseau :

docker run -d --name web --network frontend nginx:alpine

La communication entre conteneurs sur différents réseaux est bloquée sauf autorisation explicite.

8. Configurer la journalisation et la surveillance

Assurez-vous que les journaux sont capturés et rotés. La configuration du démon ci-dessus définit la journalisation en fichier JSON avec rotation. Pour la production, envisagez d'envoyer les journaux vers un système central en utilisant un pilote de journalisation comme fluentd ou splunk.

Exemple d'ajout à daemon.json :

{
  "log-driver": "fluentd",
  "log-opts": {
    "fluentd-address": "localhost:24224",
    "tag": "docker.{{.Name}}"
  }
}

Puis redémarrez Docker. Testez en exécutant un conteneur et en vérifiant la destination des journaux.

Vérification et diagnostic

Après avoir appliqué les changements, vérifiez que les contrôles de sécurité sont efficaces. Utilisez des outils automatisés et des vérifications manuelles.

1. Exécuter Docker Bench for Security

Docker Bench for Security est un script qui vérifie les meilleures pratiques courantes. Exécutez-le sur l'hôte :

git clone https://github.com/docker/docker-bench-security.git
cd docker-bench-security
sudo ./docker-bench-security.sh

La sortie est un long rapport avec des éléments [WARN], [INFO] et [PASS]. Exemple d'extrait :

[INFO] 1 - Host Configuration
[WARN] 1.1 - Ensure a separate partition for containers has been created
[PASS] 1.2 - Ensure the container host has been Hardened
[PASS] 1.3 - Ensure Docker is up to date
[INFO] 2 - Docker daemon configuration
[WARN] 2.1 - Ensure network traffic is restricted between containers on the default bridge
[PASS] 2.2 - Ensure the logging level is set to 'info'
...

Traitez les avertissements selon votre environnement. Notez que certains avertissements peuvent être acceptables en raison de contraintes opérationnelles ; documentez les exceptions.

2. Scanner les images pour les vulnérabilités

Utilisez des outils de scan d'images comme Trivy, Clair ou Docker Scout. Exemple avec Trivy :

trivy image nginx:alpine

Exemple de sortie (tronquée) :

nginx:alpine (alpine 3.18.3)
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

Si des vulnérabilités sont trouvées, mettez à jour l'image de base ou appliquez des correctifs. Intégrez le scan dans votre pipeline CI/CD pour détecter les problèmes tôt.

3. Vérifier les profils Seccomp et AppArmor

Vérifiez que les conteneurs utilisent le profil seccomp par défaut (ou un profil personnalisé).

docker inspect --format '{{.HostConfig.SecurityOpt}}' web

La sortie attendue inclut seccomp=... et éventuellement apparmor=... si AppArmor est activé.

Si vous avez un profil seccomp personnalisé, testez-le en tentant un appel système interdit à l'intérieur du conteneur. Par exemple, avec un profil qui bloque mkdir, exécuter mkdir /tmp/test devrait échouer avec Operation not permitted.

4. Tester le remappage des espaces de noms utilisateur

Après activation de userns-remap, exécutez un conteneur et vérifiez la propriété des fichiers créés dans un volume du point de vue de l'hôte.

docker run -d --name test -v /tmp/testvol:/data alpine sleep 300
docker exec test touch /data/testfile
ls -l /tmp/testvol

La sortie attendue montre testfile appartenant à dockremap (par exemple, 140000) plutôt qu'à root.

5. Confirmer l'absence de conteneurs privilégiés

Relancez la vérification des conteneurs privilégiés :

docker ps --quiet | xargs docker inspect --format '{{.Name}}: Privileged={{.HostConfig.Privileged}}'

La sortie doit afficher Privileged=false pour tous les conteneurs. Si certains sont true, remédiez immédiatement.

6. Vérifier l'isolation réseau

Testez la communication inter-conteneurs. Avec icc: false, les conteneurs sur le bridge par défaut ne peuvent pas communiquer. Créez deux conteneurs de test sur le bridge par défaut :

docker run -d --name test1 alpine sleep 300
docker run -d --name test2 alpine sleep 300

Obtenez l'IP de test1 :

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' test1

Exemple de sortie : 172.17.0.2

Depuis test2, essayez de pinger test1 :

docker exec test2 ping -c 2 172.17.0.2

Résultat attendu : le ping échoue (100% de perte de paquets) car icc est désactivé. S'ils doivent communiquer, placez-les sur un réseau défini par l'utilisateur.

7. Surveiller les anomalies d'exécution

Utilisez des outils comme Falco ou Sysdig pour détecter les comportements suspects. Installez Falco sur l'hôte selon sa documentation. Ensuite, testez en exécutant un conteneur qui tente d'écrire dans /etc à l'intérieur du conteneur :

docker run --rm -it alpine sh -c "echo bad > /etc/test"

Falco devrait générer une alerte. Exemple de ligne de journal Falco :

12:34:56.789012345: Warning Container with writable /etc directory detected (user=root command=sh container_id=abc123)

Configurez les alertes pour qu'elles aillent vers votre canal de réponse aux incidents.

Modes de défaillance et récupération

Les changements de sécurité peuvent casser les applications. Planifiez les échecs et sachez comment revenir en arrière rapidement.

Modes de défaillance courants

  • L'application nécessite des privilèges : Certaines applications ont légitimement besoin de certaines capacités ou même du mode privilégié (par exemple, démons système, outils réseau). Si vous supprimez des capacités et que l'application échoue, réajoutez uniquement les capacités nécessaires.
  • Le remappage des espaces de noms utilisateur casse les permissions de fichiers : Les volumes existants peuvent devenir inaccessibles en raison du mappage UID/GID. Solutions : recréez les volumes avec la bonne propriété, ou désactivez userns-remap.
  • Le système de fichiers racine en lecture seule cause des erreurs d'écriture : Les applications peuvent tenter d'écrire à des emplacements arbitraires. Utilisez --tmpfs ou des montages de volume pour les chemins inscriptibles requis.
  • L'isolation réseau bloque le trafic légitime : Les services internes peuvent avoir besoin de communiquer sur le bridge par défaut. Utilisez des réseaux définis par l'utilisateur avec une connectivité explicite.
  • Les limites de ressources causent des kills OOM ou une limitation : Des limites trop basses peuvent faire planter les conteneurs. Ajustez en fonction de l'utilisation observée.

Procédures de retour en arrière

Pour tout changement de configuration du démon, gardez une sauvegarde de /etc/docker/daemon.json. Pour revenir en arrière :

sudo cp /etc/docker/daemon.json.backup /etc/docker/daemon.json
sudo systemctl restart docker

Pour les changements au niveau du conteneur, recréez simplement le conteneur avec les drapeaux précédents.

Documentez les étapes exactes pour annuler chaque changement dans votre runbook.

Vérifications de récupération

Après le retour en arrière, vérifiez que l'environnement fonctionne :

  • Exécutez docker ps pour vous assurer que les conteneurs sont en cours d'exécution.
  • Vérifiez les journaux d'application pour les erreurs.
  • Testez la connectivité.
  • Relancez les commandes de vérification pertinentes de la section précédente.

Question rapide 2 sur 2

Selon le passage de conclusion, quel est l'état de sécurité par défaut des conteneurs Docker ?

Le passage indique que les conteneurs Docker sont par défaut assez sécurisés, en particulier si les processus s'exécutent en tant qu'utilisateurs non privilégiés à l'intérieur du conteneur, et suggère d'activer AppArmor, SELinux, GRSEC ou un autre système de durcissement pour plus de sécurité.

Liste de contrôle des opérations

Utilisez cette liste de contrôle pour les revues de sécurité régulières et dans le cadre de votre routine opérationnelle.

Opérations quotidiennes

  • [ ] Surveiller l'utilisation des ressources de l'hôte Docker (CPU, mémoire, disque) pour les anomalies. Responsable : ingénieur DevOps de garde. Vérifiez via les alertes Prometheus.
  • [ ] Vérifier les journaux du démon Docker (journalctl -u docker) pour les erreurs ou événements de sécurité.
  • [ ] Examiner les journaux des conteneurs pour les activités suspectes.
  • [ ] Vérifier que la surveillance/alerte (par exemple, Falco) fonctionne.

Opérations hebdomadaires

  • [ ] Exécuter Docker Bench for Security et examiner les nouveaux avertissements. Responsable : responsable sécurité.
  • [ ] Scanner les images pour les nouvelles vulnérabilités (si non intégré au CI/CD).
  • [ ] Examiner l'accès des utilisateurs aux hôtes Docker et les permissions de la socket. Responsable : responsable infrastructure.
  • [ ] Vérifier les conteneurs, images, volumes et réseaux orphelins ; nettoyer :
docker system prune -f --volumes

Attention avec --volumes car cela supprime les volumes inutilisés.

Opérations mensuelles

  • [ ] Mettre à jour le moteur Docker et la CLI vers la dernière version stable. Responsable : responsable infrastructure, planifié le premier mardi de chaque mois.
  • [ ] Examiner et mettre à jour les profils seccomp/AppArmor si nécessaire.
  • [ ] Faire tourner les secrets et identifiants utilisés par les conteneurs (par exemple, identifiants de registre, clés API).
  • [ ] Tester les procédures de sauvegarde et de restauration.
  • [ ] Examiner les limites de ressources et ajuster en fonction des tendances de performance.
  • [ ] Évaluer les nouvelles fonctionnalités de sécurité dans les versions Docker et planifier leur adoption.

Réponse aux incidents

En cas d'incident de sécurité :

  • Isolez l'hôte ou le conteneur affecté.
  • Capturez les données forensiques : journaux de conteneur, métadonnées d'image, journaux de l'hôte.
  • Identifiez la vulnérabilité (par exemple, port exposé, dépendance vulnérable).
  • Corrigez et redéployez.
  • Documentez l'incident et mettez à jour la liste de contrôle pour éviter la récurrence.

Pièges courants et comment les éviter

  1. Ignorer l'exposition de la socket Docker : De nombreux développeurs montent /var/run/docker.sock dans des conteneurs par commodité, donnant à ces conteneurs un accès équivalent à root sur l'hôte. Utilisez un proxy comme docker-socket-proxy avec un accès API en lecture seule ou restreint, et uniquement pour les conteneurs qui en ont réellement besoin.
  1. Exécuter des conteneurs en tant que root : Par défaut, les conteneurs Docker s'exécutent en root. Si un attaquant s'échappe du conteneur, il obtient root sur l'hôte. Utilisez la directive USER dans les Dockerfiles pour exécuter en tant qu'utilisateur non root, et évitez --privileged sauf nécessité absolue.
  1. Ne pas définir de limites de ressources : Sans limites de mémoire ou CPU, un seul conteneur peut épuiser les ressources de l'hôte, causant un déni de service. Définissez toujours --memory et --cpus en production, et utilisez des orchestrateurs comme Kubernetes pour appliquer des limites.
  1. Utiliser des images de base obsolètes : Les images de base contiennent souvent des vulnérabilités connues. Mettez régulièrement à jour les images et scannez-les avec des outils comme Trivy dans le CI/CD. Épinglez les versions d'image pour éviter les changements inattendus.
  1. Désactiver les fonctionnalités de sécurité pour simplifier : Désactiver seccomp, AppArmor ou SELinux pour faire fonctionner une application expose l'hôte. Créez plutôt des profils personnalisés qui n'accordent que les appels système ou permissions requis.
  1. Stocker des secrets dans les images : Coder en dur des mots de passe ou clés API dans les Dockerfiles ou variables d'environnement est une erreur courante. Utilisez les secrets Docker, les secrets Kubernetes ou des gestionnaires de secrets externes comme Vault, et ne jamais intégrer de secrets dans les couches d'image.
  1. Négliger la segmentation réseau : S'appuyer sur le réseau bridge par défaut permet à tous les conteneurs de communiquer. Utilisez des réseaux définis par l'utilisateur avec une connectivité explicite et envisagez des politiques réseau (par exemple, Calico, Cilium) dans Kubernetes.

Conclusion

La sécurité Docker n'est pas une configuration unique ; elle exige un effort opérationnel continu. Cette liste de contrôle fournit une base pour durcir votre environnement Docker, vérifier les contrôles de sécurité et récupérer après échec. Commencez par l'inventaire, appliquez les changements de configuration sûrs de manière incrémentale et établissez des cycles de revue réguliers. Adaptez la liste de contrôle à vos charges de travail et profil de risque spécifiques. En suivant ces pratiques, vous pouvez réduire considérablement la surface d'attaque de vos applications conteneurisées et maintenir une posture de sécurité robuste en production.

Recherches connexes

Score de qualité de l’article

Utilité pour le lecteur 97%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO