Sécurité11 min de lecture

Installer Docker sur un serveur sans y laisser un trou en forme de root

Le groupe docker est root sous un autre nom, le socket est un passe-partout, et le nettoyage automatique peut supprimer vos données — les trois faits qui transforment une installation Docker de cinq minutes en décision de sécurité.

Publié
14 septembre 2026
Temps de lecture
11 min de lecture
Équipe Servor
Sécurité
Tags
Docker · Containers
Read this article in English

L'installation est facile. C'est bien le problème.

Le script pratique de Docker — curl -fsSL https://get.docker.com | sh — fonctionne, et si bien qu'il masque ce qu'il vient de faire. En quelques secondes vous avez un démon qui tourne en root, un socket Unix qui peut démarrer un conteneur en root, et un groupe docker dont les membres peuvent atteindre ce socket. Chacune de ces choses est une décision de sécurité, et le script les a toutes prises pour vous sans rien demander.

La thèse ici est inconfortable et mérite d'être dite franchement : installer Docker n'est pas une tâche de gestion de paquets, c'est une tâche d'octroi de privilèges. Les commandes sont triviales. Ce qui compte, c'est de comprendre quel accès vous venez de créer, et de choisir qui l'obtient — parce que les valeurs par défaut accordent root en silence à plus de monde que vous ne le voulez probablement.

Avant d'installer : qu'y a-t-il déjà ?

Un script pratique lancé deux fois n'est pas idempotent en votre faveur — il peut tirer une méthode d'installation différente de celle déjà présente, vous laissant avec un mélange confus. Donc, regardez d'abord.

  • Docker est-il déjà installé ? command -v docker && docker --version. Si oui, vous n'installez pas — vous auditez, et peut-être nettoyez un doublon.
  • Le démon tourne-t-il ? systemctl is-active docker. Un démon en marche signifie que des conteneurs sont peut-être déjà en vol ; une réinstallation est la dernière chose à tirer à l'aveugle.
  • Qui est actuellement dans le groupe docker ? Avant d'y ajouter quiconque, sachez qui s'y trouve déjà. Chaque nom sur cette liste a un pouvoir équivalent à root sur cette machine, et les entrées oubliées sont exactement la porte oubliée dont parle la littérature du durcissement.

1. Installer le moteur — et savoir ce qu'est le démon

Que vous utilisiez le script pratique ou le dépôt de la distribution, le résultat voulu est le même : le moteur plus le plugin Compose v2, le démon activé pour qu'il survive à un redémarrage, et une preuve qu'il fait réellement tourner des conteneurs plutôt que d'être seulement installé.

Cette dernière preuve, c'est tout l'intérêt de l'image hello-world. N'importe qui peut installer un binaire ; la vérification honnête est docker run --rm hello-world qui affiche sa ligne de succès, ce qui exerce tout le chemin — démon, socket, pull d'image, démarrage du conteneur — d'un seul coup. Une chaîne de version vous dit que le client existe. Un hello-world terminé vous dit que le système marche.

Activez le démon (systemctl enable --now docker) et confirmez active, parce qu'un démon qui tourne aujourd'hui mais ne revient pas après un redémarrage est un hôte de conteneurs qui disparaît au pire moment.

2. Le groupe docker est root — traitez-le comme tel

Voici le fait que la plupart des guides mentionnent en note de bas de page et qui devrait s'imprimer en gras : ajouter un utilisateur au groupe docker équivaut à lui donner root sans mot de passe. Ce n'est pas « presque » root ni « root pour les trucs Docker ». Un membre du groupe peut lancer un conteneur qui monte tout le système de fichiers de l'hôte et lire ou écrire n'importe quel fichier en root. Il n'y a pas de frontière de privilège entre le groupe docker et root ; il y en a seulement l'apparence.

C'est pourquoi usermod -aG docker deploy est une décision, pas une commodité. Accordez-le délibérément, à des comptes à qui vous confieriez déjà sudo, et à aussi peu de monde que possible. Et connaissez le détail mécanique qui piège tout le monde : l'appartenance à un groupe ne prend effet que sur une nouvelle session de connexion. Ajoutez-vous au groupe et le shell courant ne peut toujours pas atteindre le socket — il faut se déconnecter puis se reconnecter. Ceux qui l'ignorent le « corrigent » souvent en gardant sudo docker pour toujours, ce qui masque le fait qu'ils n'avaient jamais eu besoin du groupe.

Si vous le pouvez, préférez ne pas distribuer le groupe du tout. Docker rootless et Podman existent précisément pour faire tourner des conteneurs sans démon root, et pour beaucoup de charges de travail c'est la bonne réponse. Mais si vous utilisez le groupe, le vérifier signifie contrôler que l'utilisateur prévu y est — et, tout aussi important, que personne d'autre n'y est.

3. Le socket est un passe-partout

L'erreur la plus lourde de conséquences avec Docker est d'exposer son socket. Tout ce qui peut parler à /var/run/docker.sock peut démarrer un conteneur privilégié, et un conteneur privilégié est root sur l'hôte. Cela transforme plusieurs commodités populaires en armes chargées :

  • Les interfaces de gestion qui montent le socket. Portainer, Dockge et leurs semblables sont réellement utiles, et fonctionnent en bind-montant le socket Docker — ce qui signifie que l'app web que vous venez d'exposer est root sur l'hôte. Ne publiez jamais l'une d'elles sur Internet sans une authentification forte devant, et préférez la lier au loopback derrière un reverse proxy que vous contrôlez.
  • Le socket monté en lecture-écriture dans un conteneur. Certaines stacks le demandent. En lecture seule c'est déjà mauvais ; en lecture-écriture, c'est donner les clés au conteneur. Ne le montez que si vous devez, uniquement en lecture seule, et uniquement dans des images auxquelles vous faites réellement confiance.
  • Un registre privé ou un dashboard publié sur 0.0.0.0. Liez les services internes à 127.0.0.1 et atteignez-les via un proxy qui termine le TLS et vérifie l'auth. Un registre sans TLS ni mot de passe est une invitation ouverte.

4. Un nettoyage automatique qui ne supprime pas vos données

Docker accumule : conteneurs arrêtés, images pendantes, cache de build inutilisé, et — le dangereux — les volumes. Un prune planifié empêche un hôte chargé de remplir son disque, et c'est une réellement bonne idée. C'est aussi à un flag près d'un incident de perte de données.

La règle est simple et absolue : ne jamais mettre --volumes dans un prune automatique. Les images et les conteneurs arrêtés sont reproductibles ; un volume, c'est là où vit votre base de données. Un docker system prune -af --volumes sans opérateur déclenché à trois heures du matin ne libère pas de l'espace, il supprime de l'état. Prunez les images et le cache de build sur un timer avec un filtre until pour que les couches récentes survivent ; laissez les volumes à une décision humaine délibérée. Vérifiez que le timer existe (systemctl list-timers) et lisez exactement ce qu'il lancera avant de lui faire confiance pour tourner sans opérateur.

Ce que Docker ne fait pas pour vous

Un conteneur n'est pas une frontière de sécurité comme l'est une machine virtuelle ; un exploit du noyau la traverse. Une image tirée d'un registre public est du code que vous n'avez ni écrit ni relu — latest n'est pas une version, et une image de base compromise est un hôte compromis. Docker isole des processus ; il ne vérifie pas ce qui tourne à l'intérieur, ne le corrige pas, et ne l'empêche pas d'être exposé sur un port que vous avez oublié. Et rien dans l'installation de Docker ne sauvegarde quoi que ce soit : les volumes sont à vous de protéger. La commodité n'est pas une posture de sécurité.

La vérification qui prouve la posture, pas seulement l'installation

Dans l'ordre : docker run --rm hello-world pour un moteur qui marche ; docker compose version pour le plugin ; systemctl is-enabled docker pour qu'il survive à un redémarrage ; la liste des membres du groupe docker, lue comme l'artefact de sécurité qu'elle est ; ss -tlpn pour confirmer qu'aucun dashboard, registre ou proxy de socket n'écoute sur une interface publique qu'il ne devrait pas ; et une lecture de la ligne de commande réelle de tout timer de prune, confirmant que --volumes n'y figure nulle part.

Ce que Servor apporte là-dedans

Servor livre Docker, Compose, Portainer et le prune planifié comme des recettes — parmi 150+ playbooks vérifiés — et la forme d'une recette est ce qui empêche une tâche d'octroi de privilèges d'être négligente. Une recette n'est pas un script tiré à l'aveugle : elle commence par la reconnaissance, en lisant si Docker est déjà installé et si le démon tourne, pour ne pas empiler une seconde installation sur une qui marche. Chaque étape porte sa propre vérification — la ligne de succès de hello-world, le is-active, le timer listé — si bien que le run prouve qu'il a marché. Le playbook est idempotent : un moteur existant est vérifié et rapporté, pas réinstallé.

Les guardrails sont écrits dans les recettes précisément parce que les valeurs par défaut sont dangereuses : le socket est monté en lecture seule là où il l'est, une interface de gestion n'est jamais ouverte sans auth, et le prune automatique refuse --volumes. Parce qu'ajouter un utilisateur au groupe docker accorde un pouvoir équivalent à root, cette étape est traitée comme l'opération privilégiée qu'elle est — proposée, expliquée, et approuvée par un humain, pas glissée en douce.

Et l'exécution ne quitte jamais le chemin zero-knowledge : chaque commande est signée dans votre navigateur avec une clé dérivée de votre clé de vault, relayée verbatim, et vérifiée par l'agent sur la machine avant de s'exécuter. La liste de commandes interdites, appliquée côté plan de contrôle et de nouveau côté agent, refuse le catastrophique quoi que vous approuviez. La discipline derrière cette boucle fait l'objet de l'article Plan-Execute-Verify, et le même soin appliqué à la porte d'administration se trouve dans l'article sur le durcissement SSH.

Étape suivante

Exécutez-le, ne vous contentez pas de le lire.

Gratuit pour deux serveurs, sans carte. Chaque commande est signée dans votre navigateur avant de s'exécuter — nos serveurs la relaient, ils ne peuvent pas la forger.

Continuer la lecture

Archives