Introduction
Le mode ‘rootless’ a été introduit dans Docker récemment et a quitté le statut expérimental depuis la version 20.10. Ce mode permet de lancer le daemon docker et les containeurs en tant qu’utilisateur sans les droits ‘root’ et répond dans ce sens aux principales critiques à son encontre. Ce mode comporte par contre quelques limitations de bases qui pour certaines peuvent être contournées. Nous allons voir dans cet article comment installer Docker en mode ‘rootless’ en partant d’une installation existante sur OMV 6.x.
Remarque : La procédure sera pratiquement la même sur une installation Docker effectuée dans un container LXD ou LXC. Il faudra remplacer les parties qui utilisent l’interface d’administration d’OMV par des commandes Shell.
Les principales limitations de ce mode sont :
- Les réseaux virtuels (MacVlan) ne sont pas supportés,
- appArmor n’est pas supporté,
- Le protocole SCTP n’est pas supporté,
- Il n’est pas possible d’atteindre l’adresse IP interne du containeur de l’extérieur,
- L’option expérimentale ‘checkpoint’ dans Docker n’est pas supporté,
- Les ports <1024 ne sont pas utilisables par défaut,
- Les limitations de ressources ne sont pas possibles par défaut,
- La commande ping n’est pas autorisé par défaut.
Nous verrons dans la suite de l’article que les limitations en gras sont déblocables en modifiant la configuration système.
Préparation de l’installation du mode ‘rootless’
Nous allons préparer au maximum en amont la bascule en mode ‘rootless’ pour optimiser l’installation et éviter les mauvaises surprises.
Activation des répertoires utilisateurs
L’activation des répertoires utilisateurs est un pré-requis pour utiliser le mode ‘rootless’ car il hébergera maintenant le ‘daemon’ docker. Il faut l’activer dans l’interface d’administration d’OMV. Personnellement j’ai monté le répertoire /home dans mon disque système qui reste inutilisée.
Création utilisateur ‘omdocker’
Je vous renvoie à l’article de création d’un utilisateur.
Organisation des répertoires docker (optionnelle)
Nous allons en profiter pour réorganiser l’architecture de nos répertoires contenant les configurations et les données des containeurs. Par défaut votre installation des données liées à Docker devrait se trouver dans le répertoire /var/lib/docker.
Personnellement, j’ai recréé deux répertoires :
- /srv/docker/config : Il contiendra les répertoires de toutes les configurations des containeurs,,
- /srv/docker/data : Il contiendra les répertoires des données Docker : containeurs, images, volumes… etc.
Nous aurons deux possibilités après avoir installé Docker en mode ‘Rootless’ qui dépendront surtout si vous choisissez de changer de répertoire de stockage des données Docker. Vous pourrez soit redéployer chaque containeurs en ayant pris soin d’adapter la pile si nécessaire ; soit recopier toutes les données Docker vers le nouveau répertoire. Le répertoire de configuration est lui par contre repris telle quelle.
Configuration du ‘daemon’ Docker
Le fichier de configuration ‘daemon.json’ se trouve dans le répertoire /etc/docker/ pour une installation de Docker normale. Il se situera maintenant dans le répertoire /home/omdocker/.config/docker/ de l’utilisateur ‘omdocker’ qui lancera le ‘daemon’ docker.
Vous pouvez le recopier dans votre répertoire utilisateur et modifier la ligne ‘data-root’ si nécessaire. Le mode ‘rootless’ est plus restrictif et si vous aviez sécurisé auparavant votre ‘daemon’, il faudrait modifier sa configuration. Je vous donne la configuration de mon ‘daemon’ qui fonctionne chez moi.
J’ai rajouté que la directive ‘log-driver’, ‘no-new-privileges’ et ‘live-restore’ dans le fichier : .
Configuration du firewall (optionnelle)
La ‘daemon’ Docker n’a plus les privilèges pour gérer lui-même les ‘iptables’. Il faut rajouter manuellement des règles pour les containeurs si vous avez configuré votre firewall strictement :
-
Portainer : Il faudra autoriser le port 9000 en entrée,
-
Containeurs : Il faudra ouvrir une plage de port en entrée pour tous vos containeurs,
-
Swag / Nginx : Il faudra rajouter une règle spécifique pour faire le lien entre l’adresse ip interne et l’adresse ip externe du containeur.
INPUT ACCEPT 192.168.1.0/24:ALL IP_NAS:8200-8300:TCP (Docker In) INPUT ACCEPT 192.168.1.0/24:ALL IP_NAS:9000:TCP (Portainer In) INPUT ACCEPT ALL:ALL IP_SWAG_INTERNE:80:TCP (Container) Swag In INPUT ACCEPT IP_NAS:PORT_EXT IP_SWAG_INTERNE:ALL:TCP Swag Out (Container)
Déblocage des limitations
Nous avons vu plus haut que la version ‘rootless’ avait des limitations. Nous allons ici modifier le fonctionnement du kernel pour débloquer ces limitations.
Déblocage des ports < 1024 et du ‘ping’
Les modifications s’effectuent au niveau de la configuration des variables systèmes avec le fichier /etc/sysctl.conf :
On va décommenter la ligne 28 et créer les deux lignes suivantes en fin de fichiers vers la ligne 70 :
#28 net.ipv4.ip_forward=1 # facultatif
...
#70 net.ipv4.ip_unprivileged_port_start=0
#71 net.ipv4.ping_group_range = 0 2147483647
On met à jour le système avec la commande :
Vous devriez voir en fin de commande les 3 lignes prises en compte par le système :
Déblocage des limitations de ressources
Il y a un pré-requis pour que votre système puisse utiliser les limitations de ressources ; il faut vérifier que le noyau le supporte la V2 de ‘cgroups’. Normalement Debian le supporte depuis la version 11; mais vous pouvez le vérifier en tapant la commande suivante :
Vous devriez avoir en retour apparaitre la mention V2, si votre système le supporte :
nodev cgroup
nodev cgroup2
Pour savoir quelle version votre système utilise actuellement, il faut vérifier la présence de ce fichier : /sys/fs/cgroup/cgroup.controllers. S’il existe tout va bien ; s’il n’existe pas, c’est que votre système utilise la V1 de ‘cgroups’ et il faudra modifier les paramètres de lancement du système pour utiliser la V2.
Dans le cas où le système n’utilise pas la V2, il faut créer le fichier de configuration suivant : /etc/default/grub.d/cgroup.cfg et relancer le NAS en tapant les commandes suivantes :
update-grub ; reboot
Les utilisateurs peuvent seulement utiliser les contrôleurs de type ‘memory’ et ‘pids’, il faut donc modifier la configuration de ‘systemd’ pour pouvoir utiliser les autres contrôleurs en tapant les commandes suivantes :
cat > /etc/systemd/system/user@.service.d/delegate.conf << EOF
[Service]
Delegate=cpu cpuset io memory pids
EOF
systemctl daemon-reload
Prérequis divers pour le mode ‘rootless’
Vous aurez besoin aussi d’installer ces 4 paquets supplémentaires en tapant les commandes suivantes :
sudo apt-get install -y dbus-user-session
sudo apt-get install -y slirp4netns
sudo apt-get install -y fuse-overlayfs
Installation de docker ‘rootless’
Désinstallation de la version actuelle
On commence par arrêter tous les containeurs et le daemon docker, puis on supprime tous les réseaux Docker :
sudo systemctl disable --now docker.service docker.socket
sudo docker network rm *
Puis on désinstalle ‘Portainer’ et ‘Docker’ via l’interface d’administration :
Nous recopions toutes les configurations des containeurs dans le futur emplacement si vous l’avez changé. Concernant les données des containeurs, soit vous les conserver, soit vous redéployer à nouveau tous les containeurs un par un. Pour ma part je repars sur des données ‘propre’ et je redéploierais tous les containeurs un par un avec Docker compose.
Remarque : Si vous constatez qu’il existe des ‘pids’ de containeurs (ps aux | grep docker) encore en vie, il vous faudra relancer le NAS pour ne pas perturber la suite de la procédure.
Installation de docker
On commence par installer les paquets Docker de base via le dépôt officiel, on vérifie que Docker fonctionne bien et on arrête le daemon :
sudo docker info
sudo systemctl status docker
sudo systemctl disable --now docker.service docker.socket
On termine en rajoutant l’utilisateur ‘omdocker’ au contrôleur ‘systemd’ et on vérifie :
ls /var/lib/systemd/linger
Pour l’installation du mode ‘rootless’, j’ai choisi de lancer le script d’installation avec une session utilisateur ‘Docker’ que vous avez créé en début de cet article.
Remarque : Après avoir ouvert une session ‘omdocker’, on tape la commande suivante pour relancer le daemon en tant que ‘user’ :
Installation via le gestionnaire de paquet Debian
On tape la commande suivante :
Ce package va installer le script ‘dockerd-rootless-setuptool.sh’ dans le répertoire /usr/bin. On lance l’installation avec l’utilisateur ‘omdocker’ :
sh /usr/bin/dockerd-rootless-setuptool.sh install
Installer à partir de l’URL officiel
Le script va créer un répertoire ‘bin’ dans /home/omdocker contenant les exécutables ‘Docker’ :
Vérification de l’installation
Normalement, si tout s’est bien passé, vous devriez avoir le déroulement suivant. Les variables entourées en rouge doivent apparaitre telle quelle ; si vous avez un chemin différent pour ‘DOCKER_HOST’ (avec l’ID de votre utilisateur), c’est que quelque chose cloche et que vous avez dû oublier quelque :
Par exemple, dans l’écran suivant, vous avez dû oublier de rajouter l’utilisateur au contrôleur ‘systemd’ et le chemin ‘DOCKER_HOST’ n’est pas celui qu’il devrait être. Il est très important de suivre la procédure dans cet ordre précis.
Pour terminer, il faut rajouter les deux lignes spécifiées en fin d’exécution du script à vos variables d’environnements. Ajouter-les en fin de votre ficher ‘.bashrc’ ou ‘.zshrc’ en modifiant l’ID de votre utilisateur :
export PATH=/home/omdocker/bin:$PATH
export DOCKER_HOST=unix:///run/user/1003/docker.sock
On recharge ensuite l’environnement en tapant la commande source ~/.zshrc ou source ~/.bashrc suivant le shell que vous utilisez.
On vérifie que tout est bien configuré et on insique au système de lancer docker au démarrage en tapant les commandes suivantes :
docker info
systemctl --user enable docker
Remarque : toutes les commandes ‘systemctl’ devront se faire en mode utilisateur dorénavant avec la directive ‘–user’
Tout est bon : nous utilisons ‘Syslog’, ‘Systemd’, ‘Cgroup’ version 2 et le ‘Root Dir’ a bien été pris en compte.
Installation du containeur Portainer
Remarque : si la variable d’environnement ‘DOCKER_CONTENT_TRUST’ est activée, il faut la désactiver via la commande : export DOCKER_CONTENT_TRUST=0, sinon le lancement de ‘Portainer’ vas retourner une erreur de type ‘remote trust data does not exist for docker.io’.
On va installer ‘Portainer’ en tapant la commande suivante :
docker run -d \
-p VOTRE_IP:8000:8000 \
-p VOTRE_IP:9000:9000 \
--name=portainer \
--restart=unless-stopped \
--cpus=0.5 \
--cpu-shares=512 \
--pids-limit=100 \
--memory=500m \
-v /volume/docker/config/portainer:/data \
-v /run/user/ID/docker.sock:/var/run/docker.sock \
portainer/portainer-ce:latest
Vous devrez adapter les paramètres suivant à votre configuration :
- VOTRE_IP : L’adrese IP de votre machine,
- /volume/docker/config : Le chemin vers votre config ‘Portainer’,
- ID : L’ID de votre utilisateur ‘omdocker’.
On vérifie que tout se passe bien :
On se connecte à ‘Portainer’ en tapant la commande http://VOTREIP:9000. Il est possible qu’il vous demande de relancer ‘Portainer’ lors du 1er lancement ; dans ce cas taper la commande docker restart portainer :
Nous terminons l’installation en créant un environnement de type ‘Docker standalone’ et ‘Socket’. On ne tient pas compte de la remarque concernant le montage du volume /var/run/docker.sock :
Voila notre containeur ‘Portainer’ tourne en mode ‘rootless’; il ne reste plus qu’à déployer tous vos containeurs via vos piles sauvegardées.
Redéploiement de vos containeurs
Vous aurez peut-être besoin d’adapter certaines de vos piles lors du redéploiement. Le mode ‘rootless’ peut aussi changer les UID/GID (des numéros à la place des noms d’utilisateurs et de groupes) de certains de vos répertoires de configurations de vos containeurs existants et il se peut que pour certains cela génère des perturbations. Si c’est le cas, il faudra modifier les anciens UID et GID des répertoires du containeurs qui posent des problèmes de droits d’accès. Par exemple, pour le containeur ‘Jellyfin’, le mode ‘rootless’ a changé les UID et GID (363146 / 362243) de certains répertoires, mais pas tous, ce qui engendre des problèmes de droits d’accès aux métadonnées. Il faut donc dans le cas précis modifier tous les répertoires restés avec les UID / GID ‘omdocker’ / ‘users’ :
Lors du redéploiement de vos piles, vous pouvez en profiter pour ajouter des restrictions pour sécuriser l’utilisation du kernel (voir article Sécurisé Docker) ; par exemple ici pour la pile ‘Duplicati’ :