Docker Rootless Sécurisé - Guide Complet
Installation et sécurisation de Docker en mode rootless sur Debian 13 / Ubuntu 24.04+
Table des matières
- Pourquoi Docker Rootless ?
- Prérequis
- Installation de Docker
- Configuration du mode Rootless
- Sécurisation du Daemon
- Vérification de la sécurité
- Utilisation quotidienne
- Dépannage
Pourquoi Docker Rootless ?
Docker classique tourne en root, ce qui pose des risques de sécurité :
| Mode | Risque si conteneur compromis |
| Docker root | Accès root complet à l'hôte |
| Docker rootless | Accès limité à l'utilisateur |
Protections du mode rootless :
- Le daemon Docker tourne sous votre utilisateur
- Les conteneurs utilisent des user namespaces (UIDs mappés)
- L'évasion de conteneur ne donne PAS accès root
- Isolation via seccomp, cgroups, no-new-privileges
Prérequis
Système requis
- Debian 13 (Trixie) / Ubuntu 24.04+ / Ubuntu 25.10
- Kernel 5.11+ (pour user namespaces complets)
- systemd avec support utilisateur
Vérifications préalables
# Vérifier la version du kernel
uname -r
# Vérifier que les user namespaces sont activés
cat /proc/sys/kernel/unprivileged_userns_clone
# Doit retourner 1
# Si retourne 0, activer les user namespaces :
sudo sysctl -w kernel.unprivileged_userns_clone=1
echo 'kernel.unprivileged_userns_clone=1' | sudo tee /etc/sysctl.d/99-userns.conf
Paquets nécessaires
sudo apt update
sudo apt install -y \
uidmap \
dbus-user-session \
slirp4netns \
fuse-overlayfs \
curl \
ca-certificates
Installation de Docker
1. Ajouter le dépôt officiel Docker
# Supprimer les anciennes versions
sudo apt remove -y docker docker-engine docker.io containerd runc 2>/dev/null
# Ajouter la clé GPG officielle
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Ajouter le dépôt (Ubuntu)
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Pour Debian, remplacer "ubuntu" par "debian" dans l'URL
2. Installer Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
3. Désactiver Docker système (important !)
# Arrêter et désactiver le Docker système
sudo systemctl stop docker.socket docker.service
sudo systemctl disable docker.socket docker.service
# Supprimer les données Docker système (optionnel mais recommandé)
sudo rm -rf /var/lib/docker
# Vérifier qu'il est bien arrêté
sudo systemctl status docker.service
# Doit afficher "inactive"
Configuration du mode Rootless
1. Configurer les subordinate UIDs/GIDs
Chaque utilisateur a besoin d'une plage d'UIDs subordonnés :
# Vérifier la configuration actuelle
cat /etc/subuid
cat /etc/subgid
# Ajouter votre utilisateur (remplacer $USER par votre nom d'utilisateur)
# Chaque utilisateur doit avoir une plage unique de 65536 UIDs
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
Format du fichier /etc/subuid :
username:start_uid:count
Exemple pour plusieurs utilisateurs :
alice:100000:65536
bob:165536:65536
charlie:231072:65536
2. Installer Docker Rootless
# Installer le mode rootless
dockerd-rootless-setuptool.sh install
# Si la commande n'existe pas :
sudo apt install -y docker-ce-rootless-extras
dockerd-rootless-setuptool.sh install
3. Configurer les variables d'environnement
Ajouter à votre ~/.bashrc ou ~/.zshrc :
export PATH=/usr/bin:$PATH
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
Puis recharger :
source ~/.bashrc
4. Activer le service utilisateur
# Activer le démarrage automatique
systemctl --user enable docker
# Démarrer le service
systemctl --user start docker
# Activer le linger (permet au service de tourner même sans session)
sudo loginctl enable-linger $USER
5. Vérifier l'installation
docker ps
docker run hello-world
Sécurisation du Daemon
1. Créer le fichier de configuration
mkdir -p ~/.config/docker
Créer ~/.config/docker/daemon.json :
{
"data-root": "/home/VOTRE_USER/.local/share/docker",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
},
"live-restore": true,
"no-new-privileges": true,
"default-ulimits": {
"nproc": {
"Name": "nproc",
"Soft": 4096,
"Hard": 4096
},
"nofile": {
"Name": "nofile",
"Soft": 65535,
"Hard": 65535
}
}
}
Options de sécurité expliquées :
| Option | Description |
no-new-privileges | Empêche les processus d'acquérir de nouveaux privilèges (setuid, capabilities) |
live-restore | Les conteneurs continuent de tourner si le daemon redémarre |
log-opts | Limite la taille des logs pour éviter de remplir le disque |
default-ulimits | Limite les ressources par défaut des conteneurs |
2. Utiliser un répertoire dédié (optionnel)
Pour stocker Docker sur une partition séparée :
# Créer le répertoire
sudo mkdir -p /mnt/docker
sudo chown $USER:$USER /mnt/docker
chmod 700 /mnt/docker
Modifier daemon.json :
{
"data-root": "/mnt/docker",
...
}
3. Redémarrer Docker
systemctl --user restart docker
Vérification de la sécurité
Audit complet
docker info | grep -E "Security|Rootless|no-new"
Résultat attendu :
Security Options:
seccomp
Profile: builtin
rootless
cgroupns
no-new-privileges
Vérifications individuelles
# 1. Vérifier que Docker tourne en rootless
docker info | grep -i rootless
# Doit afficher: rootless
# 2. Vérifier seccomp
docker info | grep -i seccomp
# Doit afficher: seccomp Profile: builtin
# 3. Vérifier les permissions du socket
ls -la $XDG_RUNTIME_DIR/docker.sock
# Doit appartenir à votre utilisateur, pas root
# 4. Vérifier qu'aucun Docker système ne tourne
ls -la /var/run/docker.sock 2>/dev/null && echo "ATTENTION: Docker système actif!" || echo "OK: Pas de Docker système"
# 5. Vérifier les user namespaces
docker run --rm alpine cat /proc/1/uid_map
# Les UIDs doivent être mappés (pas 0 0 4294967295)
Tableau de conformité
| Critère | Commande de vérification | Valeur attendue |
| Rootless | docker info \| grep rootless | rootless présent |
| Seccomp | docker info \| grep seccomp | Profile: builtin |
| No-new-privileges | docker info \| grep no-new | no-new-privileges présent |
| CGRoups v2 | docker info \| grep "Cgroup Version" | 2 |
| Socket utilisateur | echo $DOCKER_HOST | unix:///run/user/1000/docker.sock |
Utilisation quotidienne
Commandes de gestion du service
# Démarrer Docker
systemctl --user start docker
# Arrêter Docker
systemctl --user stop docker
# Redémarrer Docker
systemctl --user restart docker
# Voir le statut
systemctl --user status docker
# Voir les logs
journalctl --user -u docker -f
Bonnes pratiques pour les conteneurs
# Toujours utiliser un utilisateur non-root dans les conteneurs
docker run --user 1000:1000 alpine whoami
# Limiter les capabilities
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx
# Monter les volumes en lecture seule quand possible
docker run -v /data:/data:ro alpine
# Utiliser des réseaux isolés
docker network create --internal isolated_net
docker run --network=isolated_net alpine
# Limiter les ressources
docker run --memory=512m --cpus=1 alpine
Profil seccomp personnalisé (avancé)
# Télécharger le profil par défaut comme base
curl -o ~/seccomp-default.json https://raw.githubusercontent.com/moby/moby/master/profiles/seccomp/default.json
# Utiliser un profil personnalisé
docker run --security-opt seccomp=~/seccomp-custom.json alpine
Dépannage
Erreur: "failed to setup UID/GID map"
Cause : Mauvaise configuration de /etc/subuid ou /etc/subgid
Solution :
# Vérifier la configuration
cat /etc/subuid
cat /etc/subgid
# Corriger (remplacer USER par votre nom d'utilisateur)
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
# Redémarrer Docker
systemctl --user restart docker
Erreur: "Start request repeated too quickly"
Cause : Le service a échoué plusieurs fois
Solution :
# Réinitialiser le compteur d'échecs
systemctl --user reset-failed docker
# Attendre quelques secondes
sleep 5
# Redémarrer
systemctl --user start docker
Erreur: "Cannot connect to the Docker daemon"
Cause : Variable DOCKER_HOST non définie ou service arrêté
Solution :
# Vérifier que DOCKER_HOST est défini
echo $DOCKER_HOST
# Doit afficher: unix:///run/user/1000/docker.sock
# Si vide, définir la variable
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
# Vérifier que le service tourne
systemctl --user status docker
# Le démarrer si nécessaire
systemctl --user start docker
Le service ne démarre pas au boot
Cause : Linger non activé
Solution :
sudo loginctl enable-linger $USER
Performances réseau lentes
Cause : slirp4netns par défaut
Solution (optionnel) :
Utiliser pasta au lieu de slirp4netns pour de meilleures performances :
sudo apt install passt
# Dans ~/.config/systemd/user/docker.service.d/override.conf
[Service]
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_NET=pasta"
Ressources
╔══════════════════════════════════════════════════════════════╗
║ Docker Rootless Manager ║
╚══════════════════════════════════════════════════════════════╝
Usage: docker-manager.sh [commande]
Installation:
install Installation complète de Docker rootless sécurisé
install-deps Installer uniquement les dépendances
setup-rootless Configurer le mode rootless (Docker déjà installé)
Service:
start Démarrer Docker
stop Arrêter Docker
restart Redémarrer Docker
status Afficher le statut du service
logs Afficher les logs en temps réel
Sécurité:
audit Audit de sécurité complet
secure Appliquer la configuration sécurisée
Maintenance:
info Afficher les informations Docker
cleanup Nettoyer les ressources non utilisées
nuke Supprimer TOUTES les données Docker
Aide:
help Afficher cette aide
``