Installer Docker Engine proprement
Pourquoi
Installer Docker prend cinq minutes, et c'est précisément le problème : la plupart des installations sont faites en cinq minutes, avec la première commande trouvée, puis plus personne n'y touche. Six mois plus tard apparaissent les symptômes d'une installation bâclée :
- le disque du serveur est plein, parce qu'un conteneur bavard a écrit 40 Go de journaux qu'aucune rotation ne limitait ;
- l'application d'un client ne joint plus son annuaire LDAP, parce que le réseau créé par Docker a pris la même plage d'adresses que le VPN de l'entreprise ;
- un compte de service compromis a pris le contrôle total du serveur, parce qu'on l'avait ajouté au groupe
docker« pour ne pas avoir à taper sudo » ; - une mise à jour automatique du moteur a redémarré toutes les applications un mardi à 14 h.
Chacun de ces incidents se prévient au moment de l'installation, en quelques lignes. Cette leçon installe Docker Engine sur Ubuntu 24.04 et pose ces quelques lignes. La procédure est identique sur Debian, à l'adresse du dépôt près.
Les concepts
D'où viennent les paquets
Quatre sources sont possibles sur une distribution Debian ou Ubuntu, et le choix n'est pas anodin.
| Source | Paquets | Version au 1er octobre 2026 | Pour | Contre |
|---|---|---|---|---|
| Dépôt de la distribution | docker.io | 29.1.3 (Ubuntu 24.04), 26.1.5 (Debian 13) | Correctifs de sécurité suivis par l'équipe de la distribution, aucune source tierce | Version plus ancienne, plugins (Compose, Buildx) parfois absents ou en retard |
| Dépôt officiel Docker | docker-ce, containerd.io... | 29.8.2 | Dernière version stable, tous les plugins, documentation alignée | Dépôt tiers auquel il faut faire confiance, mises à jour plus fréquentes à suivre |
Script get.docker.com | Ceux du dépôt officiel | Idem | Rapide pour un poste de test | Exécute un script distant en root sans contrôle ; déconseillé par Docker lui-même en production |
| Paquet Snap | docker | Variable | Mises à jour automatiques | Confinement qui casse des montages et des chemins ; non supporté par Docker |
Pour un serveur ou un poste de travail, le choix se fait entre les deux premières lignes. Ce cours utilise le dépôt officiel Docker, parce qu'il fournit les mêmes versions que la documentation et les plugins Compose et Buildx à jour. Le paquet de la distribution est un choix tout à fait défendable sur un serveur où l'on veut un seul canal de mises à jour de sécurité ; c'est alors l'équipe de la distribution qui rétroporte les correctifs.
On ne mélange jamais les deux : les paquets docker.io (distribution) et docker-ce (Docker) se marchent dessus, tout comme les paquets containerd et containerd.io.
Les paquets installés
Le dépôt officiel fournit cinq paquets principaux :
docker-ce: le démondockerd(Community Edition) ;docker-ce-cli: le clientdocker;containerd.io: containerd et runc ;docker-buildx-plugin: le constructeur BuildKit, appelé pardocker build;docker-compose-plugin: Compose, appelé pardocker compose.
Un sixième, docker-ce-rootless-extras, s'installe en dépendance recommandée et apporte le mode rootless.
Trois façons d'accéder au démon
Après l'installation, le socket /var/run/docker.sock n'est accessible qu'à root et au groupe docker. Trois politiques sont possibles :
- Passer par
sudo. Chaque commande Docker est une commande d'administration, tracée dans les journaux desudo. C'est le plus honnête sur un serveur. - Ajouter l'utilisateur au groupe
docker. Pratique sur un poste de développement personnel, mais l'utilisateur devient root sans mot de passe. Nous allons le démontrer. - Le mode rootless. Chaque utilisateur fait tourner son propre démon Docker, sans aucun privilège, dans un user namespace. C'est le mode le plus sûr, avec quelques limites fonctionnelles présentées à la leçon 12.
En pratique
Note
Les sorties de cette partie ont été obtenues en root dans un environnement de laboratoire Ubuntu 24.04 vierge (un conteneur privilégié jetable, dans lequel on peut installer et faire tourner un second Docker). Sur votre machine, gardez les sudo.
1. Retirer les paquets concurrents
$ sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc | cut -f1)
Reading state information...
0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded.
dpkg --get-selections ne renvoie que les paquets de cette liste qui sont réellement installés ; sur une machine vierge, il n'y a rien à retirer. apt remove conserve les données de /var/lib/docker : vos images et volumes éventuels ne sont pas supprimés.
2. Déclarer le dépôt et sa clé
$ sudo apt update
$ sudo apt install ca-certificates curl
$ sudo install -m 0755 -d /etc/apt/keyrings
$ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
$ sudo chmod a+r /etc/apt/keyrings/docker.asc
On télécharge la clé publique OpenPGP avec laquelle Docker signe son dépôt et on la range dans /etc/apt/keyrings, le répertoire prévu pour les clés de dépôts tiers. Les options de curl : -f échoue sur une erreur HTTP au lieu d'enregistrer la page d'erreur, -sS est silencieux sauf en cas d'erreur, -L suit les redirections.
Avant de faire confiance à cette clé, vérifiez son empreinte :
$ gpg --show-keys /etc/apt/keyrings/docker.asc
pub rsa4096 2017-02-22 [SCEA]
9DC858229FC7DD38854AE2D88D81803C0EBFCD88
uid Docker Release (CE deb) <docker@docker.com>
sub rsa4096 2017-02-22 [S]
L'empreinte 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 est celle publiée par Docker dans sa documentation. Si elle diffère, arrêtez-vous et vérifiez avant d'aller plus loin : soit Docker a changé de clé (ce serait annoncé dans sa documentation), soit quelqu'un s'est intercalé entre vous et download.docker.com.
Déclarez ensuite le dépôt au format deb822 (un fichier .sources), le format moderne d'APT :
$ sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: noble
Components: stable
Architectures: amd64
Signed-By: /etc/apt/keyrings/docker.asc
Le shell a remplacé les deux expressions $(...) avant d'écrire le fichier : noble est le nom de code d'Ubuntu 24.04, lu dans /etc/os-release ; amd64 est l'architecture du système. La ligne Signed-By est importante : elle limite cette clé à ce seul dépôt. Une clé ajoutée à l'ancienne mode avec apt-key était au contraire acceptée pour signer n'importe quel dépôt, ce qui donnait à Docker (ou à quiconque volerait sa clé) le pouvoir de remplacer n'importe quel paquet du système.
$ sudo apt update 2>&1 | grep -i docker
Get:2 https://download.docker.com/linux/ubuntu noble InRelease [48.5 kB]
Get:4 https://download.docker.com/linux/ubuntu noble/stable amd64 Packages [81.4 kB]
3. Choisir la version et installer
Voyons ce que le dépôt propose :
$ apt-cache madison docker-ce | head -4
docker-ce | 5:29.8.2-1~ubuntu.24.04~noble | https://download.docker.com/linux/ubuntu noble/stable amd64 Packages
docker-ce | 5:29.8.1-1~ubuntu.24.04~noble | https://download.docker.com/linux/ubuntu noble/stable amd64 Packages
docker-ce | 5:29.8.0-1~ubuntu.24.04~noble | https://download.docker.com/linux/ubuntu noble/stable amd64 Packages
docker-ce | 5:29.7.2-1~ubuntu.24.04~noble | https://download.docker.com/linux/ubuntu noble/stable amd64 Packages
Le 5: en tête est une époque Debian, un compteur qui prime sur le reste du numéro ; il faut le reprendre tel quel. Sur un poste de travail, on installe simplement la dernière version. Sur un parc de serveurs, on épingle la version, pour que tous les serveurs aient la même et que les mises à jour soient une décision. Ce cours a été vérifié avec la 29.8.1 :
$ V=5:29.8.1-1~ubuntu.24.04~noble
$ sudo apt install docker-ce=$V docker-ce-cli=$V docker-ce-rootless-extras=$V \
containerd.io docker-buildx-plugin docker-compose-plugin
$ dpkg -l | grep -E "docker|containerd" | awk '{print $2, $3}'
containerd.io 2.3.6-1~ubuntu.24.04~noble
docker-buildx-plugin 0.37.1-1~ubuntu.24.04~noble
docker-ce 5:29.8.1-1~ubuntu.24.04~noble
docker-ce-cli 5:29.8.1-1~ubuntu.24.04~noble
docker-ce-rootless-extras 5:29.8.1-1~ubuntu.24.04~noble
docker-compose-plugin 5.5.1-1~ubuntu.24.04~noble
Pour qu'un apt upgrade de routine ne fasse pas évoluer le moteur dans votre dos, mettez-le en attente (sur un parc de serveurs, épinglez et mettez en attente de la même façon containerd.io, qui contient containerd et runc, et dont les mises à jour corrigent régulièrement des failles : elles doivent être appliquées, mais à un moment choisi) :
$ sudo apt-mark hold docker-ce docker-ce-cli
docker-ce set on hold.
docker-ce-cli set on hold.
On lèvera l'attente avec apt-mark unhold le jour où l'on décidera de la mise à jour, après l'avoir testée. Rappel de la leçon précédente : mettre à jour docker-ce redémarre le démon, donc les conteneurs si live-restore n'est pas activé.
Sur Ubuntu, le paquet active et démarre aussitôt les services docker et containerd ; vérifiez-le avec systemctl status docker.
4. Le test de fumée
$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
4f55086f7dd0: Pulling fs layer
4f55086f7dd0: Download complete
4f55086f7dd0: Pull complete
d5e71e642bf5: Download complete
Digest: sha256:5e23090353324d887c48ad5e5c56d294eab81588df9605b07d1afe895f9cc8f8
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
...
(Sortie abrégée : la fin du message propose des pistes pour continuer.)
Ce test valide toute la chaîne de la leçon 3 : client, démon, accès au registre Docker Hub, containerd, runc, et le retour de la sortie vers votre terminal. Si l'une de ces étapes échoue, le message d'erreur dit laquelle.
5. Les droits d'accès, en connaissance de cause
Un utilisateur ordinaire, alice, essaie Docker :
alice$ docker ps
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock
La solution qu'on trouve partout consiste à ajouter alice au groupe docker. Faisons-le, puis vérifions ce que cela implique :
$ sudo usermod -aG docker alice
alice$ id
uid=1001(alice) gid=1001(alice) groups=1001(alice),995(docker)
alice$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
-aG ajoute (append) le groupe sans retirer les autres ; sans le -a, alice perdrait tous ses groupes secondaires. Le nouveau groupe n'est pris en compte qu'à la prochaine connexion d'alice.
alice n'est pas administratrice. Elle ne peut pas lire le fichier des empreintes de mots de passe :
alice$ cat /etc/shadow
cat: /etc/shadow: Permission denied
Mais elle peut demander au démon, qui est root, de monter /etc dans un conteneur :
alice$ docker run --rm -v /etc:/hote-etc:ro alpine:3.22 head -2 /hote-etc/shadow
root:*:20707:0:99999:7:::
daemon:*:20707:0:99999:7:::
La démonstration se limite à une lecture, mais rien n'empêchait alice de monter / en écriture et d'ajouter une ligne à /etc/sudoers. Le groupe docker donne un accès root sans mot de passe et sans trace dans les journaux de sudo. La documentation de Docker le dit sans détour : seuls des utilisateurs de confiance doivent pouvoir contrôler le démon.
D'où la règle de ce cours :
- sur un poste de développement personnel, le groupe
dockerest acceptable : vous êtes déjà administrateur de votre machine ; - sur un serveur, on n'ajoute personne au groupe
docker; les administrateurs utilisentsudo, et les comptes de déploiement passent par un outil qui encadre ce qu'ils peuvent faire ; - sur un poste partagé ou pour des usagers non administrateurs, on utilise le mode rootless.
6. Une configuration de démon saine
La configuration de dockerd vit dans /etc/docker/daemon.json, qui n'existe pas après l'installation. Avant d'en écrire un, observons deux réglages par défaut.
Les journaux ne sont pas limités. Le pilote de journalisation par défaut est json-file, et il ne fait aucune rotation :
$ docker info --format '{{.LoggingDriver}}'
json-file
$ docker run -d --name bavard alpine:3.22 sh -c 'while true; do echo "$(date) une ligne de journal assez longue pour remplir le disque petit à petit"; done'
$ sleep 10; sudo du -h $(docker inspect bavard --format '{{.LogPath}}')
2.4M /var/lib/docker/containers/0be41391.../0be41391...-json.log
$ docker rm -f bavard
2,4 Mo en dix secondes, soit environ 860 Mo par heure et plus de 20 Go par jour, pour un seul conteneur qui écrit en boucle. Une application qui part en erreur et journalise chaque tentative de reconnexion produit exactement ce profil.
Les réseaux prennent des plages privées larges. Docker attribue à ses réseaux des sous-réseaux tirés de plages privées (RFC 1918), par défaut en /16 dans 172.17.0.0 à 172.31.0.0, puis dans 192.168.0.0/16 :
$ docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
172.18.0.0/16
$ docker network create test1
$ docker network inspect test1 --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
172.19.0.0/16
$ docker network rm test1
(Le pont par défaut a pris 172.18.0.0/16 et non 172.17.0.0/16 parce que cette dernière plage était déjà utilisée par le réseau de la machine de laboratoire : Docker évite les plages qu'il voit déjà sur les interfaces de l'hôte.) Le piège est que Docker ne voit pas les réseaux qui ne sont pas encore là : une route poussée plus tard par un VPN, ou un réseau distant joint à travers un routeur. Si l'entreprise utilise 172.19.0.0/16 pour ses serveurs internes, tout le trafic du serveur vers ces adresses part désormais dans le réseau Docker.
Écrivons une configuration qui traite ces deux points, et active live-restore :
{
"log-driver": "local",
"log-opts": {
"max-size": "10m",
"max-file": "5"
},
"live-restore": true,
"bip": "10.200.0.1/24",
"default-address-pools": [
{"base": "10.201.0.0/16", "size": 24}
]
}log-driver: local: un format binaire compact, compressé à la rotation, recommandé par Docker pour la plupart des usages. Il fait une rotation par défaut (5 fichiers de 20 Mo) ; on la règle ici explicitement à 5 fichiers de 10 Mo, soit 50 Mo au plus par conteneur.docker logscontinue de fonctionner. Si un agent de collecte lit directement les fichiers JSON des conteneurs, gardezjson-fileen lui ajoutant les mêmesmax-sizeetmax-file.live-restore: true: les conteneurs survivent à un redémarrage dedockerd.bip: l'adresse et la plage du pont par défautdocker0.default-address-pools: la réserve dans laquelle Docker découpe les réseaux qu'il crée, ici des/24(254 adresses, bien assez pour un réseau d'application) pris dans10.201.0.0/16. Choisissez ces plages avec l'équipe réseau, dans un espace dont on sait qu'il ne sera jamais routé vers ce serveur.
Validez avant de redémarrer. Une erreur de syntaxe dans daemon.json empêche dockerd de démarrer, et avec lui toutes les applications du serveur :
$ sudo dockerd --validate --config-file /etc/docker/daemon.json
configuration OK
$ sudo systemctl restart docker
Vérifions l'effet :
$ docker info --format '{{.LoggingDriver}} live-restore={{.LiveRestoreEnabled}}'
local live-restore=true
$ docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
10.200.0.0/24
$ docker network create test1
$ docker network inspect test1 --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
10.201.0.0/24
$ docker network rm test1
Warning
Les réglages de journalisation ne s'appliquent qu'aux conteneurs créés après le redémarrage. Les conteneurs existants gardent leur configuration jusqu'à ce qu'on les recrée. De même, les réseaux déjà créés conservent leur plage.
Sous le capot
Que font les paquets lors de leur installation ? Ils déposent les binaires dans /usr/bin (dockerd, docker-proxy, docker-init), créent le groupe système docker, installent trois unités systemd (docker.service et docker.socket pour docker-ce, containerd.service pour containerd.io) et les activent.
Au premier démarrage, dockerd :
- crée le pont
docker0et choisit sa plage d'adresses ; - installe ses chaînes de pare-feu (
DOCKER,DOCKER-USER,DOCKER-ISOLATION-...) dans iptables, ou dans nftables si le moteur expérimental de pare-feu nftables est configuré ; - active le routage IP du noyau (
net.ipv4.ip_forward = 1) pour que les conteneurs puissent sortir vers l'extérieur, ce qui peut transformer en routeur un serveur qui n'était pas censé l'être (la leçon 10 y revient) ; - prépare ses répertoires sous
/var/lib/dockeret laisse containerd préparer les siens sous/var/lib/containerd.
Le fichier daemon.json et les options passées sur la ligne de commande de dockerd sont deux façons de régler les mêmes paramètres. Si un même paramètre est défini aux deux endroits, dockerd refuse de démarrer : ne définissez donc rien dans l'unité systemd que vous définissez dans daemon.json, et réciproquement.
Pièges courants
usermod -aG docker « ne marche pas ». Le groupe n'est lu qu'à l'ouverture de session. Déconnectez-vous et reconnectez-vous, ou lancez newgrp docker dans le terminal courant. id doit afficher le groupe docker.
Deux Docker sur la même machine. Après avoir suivi deux tutoriels différents, on se retrouve avec docker.io et docker-ce, ou avec un Docker installé par Snap en plus de celui d'APT. Les symptômes sont étranges : des images qui « disparaissent », deux sockets, des versions client et serveur incohérentes dans docker version. Vérifiez avec dpkg -l | grep -E 'docker|containerd' et snap list 2>/dev/null | grep docker, puis gardez une seule source.
Le script rootless refuse de s'installer. L'outil dockerd-rootless-setuptool.sh s'arrête si un Docker « rootful » est déjà accessible à l'utilisateur :
alice$ dockerd-rootless-setuptool.sh check
[ERROR] Aborting because rootful Docker (/var/run/docker.sock) is running and accessible. Set --force to ignore.
C'est voulu : les deux démons cohabiteraient et l'on ne saurait plus lequel répond. Retirez l'utilisateur du groupe docker (ou désactivez le démon système) avant de passer en mode rootless.
daemon.json invalide et Docker ne redémarre plus. Une virgule en trop suffit. Le diagnostic se lit avec journalctl -u docker -n 50, mais le mieux est de ne jamais redémarrer sans dockerd --validate.
Le pare-feu UFW contourné. Sur Ubuntu, les ports publiés par Docker avec -p sont joignables depuis l'extérieur même si UFW les interdit, parce que les règles de Docker s'appliquent avant celles d'UFW. C'est l'un des pièges les plus graves de Docker ; la leçon 10 l'explique et le corrige.
Sécurité
- Vérifiez l'origine des paquets. L'empreinte de la clé, la ligne
Signed-Bylimitée au dépôt Docker, et jamais decurl ... | sudo shsur un serveur. - Personne dans le groupe
dockersur un serveur. Faites l'inventaire régulièrement :getent group docker. C'est une vérification classique des audits de sécurité, et un point de contrôle des guides de durcissement comme le CIS Docker Benchmark. - Mettez à jour le moteur. Docker, containerd et runc ont des failles de sécurité régulières, parfois critiques (évasions de conteneur). Épingler une version ne veut pas dire la figer : cela veut dire choisir le moment de la mise à jour. Abonnez-vous aux avis de sécurité de Docker et de votre distribution.
- Les journaux sont aussi une question de sécurité. Un disque plein arrête la journalisation du système, la base de données et parfois l'authentification. La rotation des journaux protège la disponibilité.
En production
Sur un parc de serveurs, cette installation ne se fait pas à la main. On la décrit dans un outil de gestion de configuration (Ansible, par exemple, traité dans le chapitre Héberger) ou dans une image de machine préparée à l'avance, avec :
- la version de Docker épinglée et identique partout ;
- le même
daemon.jsonpartout, avec des plages d'adresses validées par l'équipe réseau ; - les mises à jour du moteur planifiées, testées sur un serveur de recette, puis déployées serveur par serveur ;
- une supervision de l'espace disque de
/var/lib/dockeret/var/lib/containerd, qui grossissent avec les images et les volumes (la commandedocker system dfdonne la répartition).
Et sur Kubernetes ? Les nœuds Kapsule de Scaleway sont fournis avec containerd déjà installé et configuré par Scaleway, sans Docker Engine. Vous n'installez rien sur les nœuds : tout ce qui précède concerne vos postes de développement, vos serveurs de CI et les serveurs qui exécutent Docker directement.
Exercices
1. Inventaire. Sur une machine où Docker est installé, déterminez : la source des paquets (distribution ou dépôt Docker), la version exacte du moteur, la liste des membres du groupe docker, le pilote de journalisation et l'état de live-restore.
Solution
$ dpkg -l | grep -E 'docker|containerd'
$ apt-cache policy docker-ce docker.io
$ docker version --format '{{.Server.Version}}'
$ getent group docker
$ docker info --format '{{.LoggingDriver}} live-restore={{.LiveRestoreEnabled}}'
docker-ce désigne le dépôt officiel, docker.io la distribution ; apt-cache policy montre en plus l'URL du dépôt d'origine. getent group docker liste les membres en dernier champ.
2. Plages d'adresses. Le réseau interne d'un client utilise 10.0.0.0/8 en totalité, et son VPN pousse des routes vers 172.16.0.0/12. Proposez une configuration default-address-pools et bip pour les serveurs Docker que Lyneko lui installe.
Solution
Il reste la plage 192.168.0.0/16 dans l'espace RFC 1918. Après validation avec l'équipe réseau du client, on peut par exemple garder 192.168.0.0/24 pour le pont par défaut et réserver la moitié haute aux réseaux Docker :
{
"bip": "192.168.0.1/24",
"default-address-pools": [
{"base": "192.168.128.0/17", "size": 24}
]
}Cela donne 128 réseaux /24, de 192.168.128.0/24 à 192.168.255.0/24, sans chevauchement avec bip. Si même cet espace est utilisé chez le client, l'espace partagé 100.64.0.0/10 (RFC 6598) est parfois retenu, en concertation. L'essentiel : la décision se prend avec l'équipe réseau, et elle est écrite dans la configuration avant le premier démarrage.
3. Rotation sur un conteneur existant (niveau 200). Vous venez de déployer le daemon.json de cette leçon sur un serveur qui fait déjà tourner un conteneur api. Comment vérifiez-vous si api bénéficie de la rotation, et que faites-vous sinon ?
Solution
docker inspect api --format '{{.HostConfig.LogConfig}}' affiche le pilote et les options du conteneur. S'il montre encore {json-file map[]}, le conteneur a été créé avant le changement. Il faut le recréer (pas seulement le redémarrer) : docker rm -f api puis le relancer avec les mêmes options, ou docker compose up -d --force-recreate api s'il est géré par Compose (leçon 11). Un simple docker restart ne change pas la configuration d'un conteneur.
4. Politique d'accès. Rédigez la politique d'accès à Docker pour trois contextes : le portable d'un développeur, un serveur de CI partagé par dix projets, un serveur de production.
Solution
Portable : groupe docker acceptable, ou mode rootless pour les plus prudents. Serveur de CI partagé : surtout pas le groupe docker pour les tâches de CI (n'importe quel projet pourrait prendre le contrôle du serveur et lire les secrets des autres) ; on isole chaque tâche dans une VM éphémère, ou l'on utilise des constructions sans démon privilégié (BuildKit rootless, Kaniko, Buildah). Production : aucun membre du groupe docker, administration par sudo tracé, déploiements par un outil qui encadre les actions (Compose piloté par une CI via SSH avec un compte restreint, ou mieux un orchestrateur).
Récapitulatif
- Choisissez une source de paquets : le dépôt officiel Docker (versions récentes, plugins) ou le paquet de la distribution (canal de sécurité unique). Jamais les deux, jamais Snap, jamais
curl | shen production. - Vérifiez l'empreinte de la clé et limitez-la au dépôt avec
Signed-By. Épinglez la version sur les serveurs. - Le groupe
dockeréquivaut à root sans mot de passe. Acceptable sur votre poste, pas sur un serveur. - Dès le premier jour : rotation des journaux, plages d'adresses choisies, live-restore, et
dockerd --validateavant chaque redémarrage.
Pour aller plus loin
- La page Docker security de la documentation officielle, section « Docker daemon attack surface ».
- Le CIS Docker Benchmark, référentiel de durcissement utilisé par les auditeurs ; l'outil libre docker-bench-security en automatise la vérification.
- La référence complète de
daemon.jsondans la documentation dedockerd. - Leçon suivante :
docker rundécortiqué, option par option.
Sources
- Docker, Install Docker Engine on Ubuntu
- Docker, Linux post-installation steps
- Docker, Rootless mode
- Docker, Docker daemon attack surface
- Docker, Local file logging driver
- Docker, dockerd : fichier de configuration du démon
- Paquet docker.io dans Ubuntu (Launchpad)
- Paquet docker.io dans Debian (tracker)
- RFC 1918, Address Allocation for Private Internets