Installer Docker en mode « Rootless »

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.

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érimental ‘checkpoint’ dans Docker n’est pas supporté,
  • Les ports <1024 ne sont pas utilisables par défaut,
  • Les limitations de ressources ne sont pas possible 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 et orange 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.

activation repertoire
Activation des répertoires utilisateurs

Création utilisateur ‘omdocker’

Je vous renvoi à l’article de création d’un utilisateur ‘omdocker’

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 re-créé 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 installer Docker en mode ‘Rootless’ qui dépendront surtout si vous choisissez de changer de répetoire de stockage des données Doker. Vous pourrez soit re-deployer 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écuriser auparavant votre ‘daemon’, il faudra 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 daemon docker en mode rootless
Configuration du daemon docker en mode ‘rootless’

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 configurer 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 vas décommenter la ligne 28 et créer les deux lignes suivantes en fin de fichiers vers la ligne 70 : ‘sudo nano /etc/sysctl.conf

#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 : ‘sudo sysctl –system‘. Vous devriez voir en fin de commande les 3 lignes prises en compte par le système :

variables systèmes
Modifications des variables systèmes

Déblocage des limitations de ressources

Il y a un pré-requis pour que votre système puisse utilisé 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 :

$ grep cgroup /proc/filesystems

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 vas 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 ou le système n’utilise pas la V2, il faut créer le ficher de configuration suivant : ‘/etc/default/grub.d/cgroup.cfg‘ et relancer le NAS en tapant les commandes suivantes :

$ sudo echo "systemd.unified_cgroup_hierarchy=true" > cgroup.cfg
$ 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 :

$ mkdir -p /etc/systemd/system/user@.service.d
$ 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 install uidmap
$ 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 docker stop $(sudo docker ps -a -q)
$ sudo systemctl disable --now docker.service docker.socket
$ sudo docker network rm *

Puis on désinstalle ‘Portainer’ et ‘Docker’ via l’interface d’administration :

Suppression de portainer
Suppression de ‘Portainer’

Suppression de docker
Suppression de ‘Docker’

Nous recopions toutes les configurations des containeurs dans le futur emplacement si vous l’avez changer. 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éployerais 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 apt install docker-ce docker-ce-cli containerd.io
$ 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 :

$ loginctl enable-linger omdocker
$ ls /var/lib/systemd/linger

Pour l’installation du mode ‘rootless’, vous avez deux possibilités. J’ai choisi personnellement la 2eme solution. Avant de lancer le script d’installation et pour la 2eme solution, il faut ouvrir une session utilisateur avec l’utilisateur ‘Docker’ que vous avez créer 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’ : ‘systemctl –user daemon-reload

Installation via le gestionnaire de paquet Debian

$ sudo apt-get install -y docker-ce-rootless-extras

Ce package vas installer le script ‘dockerd-rootless-setuptool.sh‘ dans le répertoire /usr/bin. On lance l’installation avec l’utilisateur ‘omdocker’ :

$ su omdocker
$ sh /usr/bin/dockerd-rootless-setuptool.sh install

L’installer directement à partir de l’URL officiel

Le scrip vas créer un répertoire ‘bin’ dans /home/omdocker contenant les exécutables ‘Docker’.

$ curl -fsSL https://get.docker.com/rootless | sh

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 du oublier quelque :

Installation de docker rootless
Installation de docker ‘rootless’

Par exemple dans l’écran suivant, vous avez du 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.

Installation échouée
Problème d’installation mode ‘rootless’

Pour terminer il faut rajouter les deux lignes spécifiés 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 celui que vous utiliser.

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 :

Remarque : toute les commandes ‘systemctl‘ devront se faire en mode utilisateur dorénavant avec la directive ‘–user

$ systemctl --user status docker
$ docker info
$ systemctl --user enable docker

docker tourne en mode rootless
Docker tourne en mode ‘rootless’

informations du daemon Docker
Informations du daemon Docker

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’environnent ‘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 vas installer ‘Portainer’ en tapant la commande suivante; vous devrez adapter les paramètres en gras à votre configuration :

$ 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

On vérifie que tout se passe bien :

installation containeur portainer
Installation du containeur ‘Portainer’

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‘ :

redémarrage de Portainer nécessaire
Redémarrage de ‘Portainer’ nécessaire dans certains cas

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‘ :

Création de l'environnement Portainer
Création de l’environnement ‘Portainer’

Voila notre containeur ‘Portainer’ tourne en mode ‘rootless’; il ne reste plus qu’à déployer tous vos containeurs via vos piles sauvegardées.

Le containeur Portainer est lancé en rootless
Le containeur ‘Portainer’ est lancé en rootless

Portainer est fonctionnel
Portainer est fonctionnel

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’ :

changement du propriétaire des répertoires
changement du propriétaire des répertoires

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écuriser docker) ; par exemple ici pour la pile ‘Duplicati’ :

Pile Duplicati avec des restrictions d'utilisation
Pile ‘Duplicati’ avec des restrictions d’utilisation

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *