Historiquement, Docker a toujours exigé des privilèges root pour s’exécuter. En effet, certaines fonctionnalités telles que les espaces de noms ou les points de montage qui constituent la base de Docker ont toujours requis des privilèges élevés. 

Étant donné que Docker est composé d’une pile entière de processus sous-jacent (runc, containerd, dockerd, etc.). L’exécution de docker mode Rootless signifie donc que l’intégralité de la stack docker sera exécutée en mode Rootless. De plus, étant donné que dockerd lui-même s’exécute en tant qu’utilisateur non root, les conteneurs lancés n’auront également aucun privilège root associé.

Ce mode, qui constitue une bonne pratique recommandé par l’ANSI protège le système hôte contre des attaques qui pourraient exploiter des vulnérabilités potentielles du code de l’application ou d’erreurs de configuration.

Guide https://www.ssi.gouv.fr/uploads/2020/12/docker_fiche_technique.pdf

I. Prérequis et environnement de test

  • Ne pas avoir docker « normal » d’installé sur la machine hôte
  • Dans mon cas, mon hôte docker sera : Ubuntu 20.04.X

II. Choses que vous ne pourrez pas faire avec docker Rootless

Etant donnez que le deamon Docker ne fonctionnera pas avec root, vous ferez face à quelques restrictions comme :

  • L’impossibilité d’exposer un conteneur sur un port privilégié (port < 1024). Exemple de message d’erreur avec un conteneur Nginx « bindé » sur le port 80 (hôte).
docker run -p 80:80 -d nginx
...
cannot expose privileged port 80, you can add 'net.ipv4.ip_unprivileged_port_start=80' to /etc/sysctl.conf (currently 1024), or set CAP_NET_BIND_SERVICE on rootlesskit binary, or choose a larger port number (>= 1024): listen tcp4 0.0.0.0:80: bind: permission denied.
  • L’utilisateur du conteneur docker sera toujours root, mais se sera un compte que je vais appeler « root light« , car il n’aura pas accès à certain fichiers comme : /mnt/etc/shadow (dans le cas où vous montez tout ou partie du système hôte en tant que volume dans le conteneur. Cela ne vous arrivera jamais, ou alors si vous essayez de faire une escalade privilège). ^^
  • Toutes autres manœuvres nécessitant un accès super utilisateur seront aussi prohibées. Par exemple :
    • le lancement de processus nécessitant un accès privilégié
    • L’allocation de ressources physiques customisé pour un conteneur : CPU,RAM)

III. Installation de Docker Rootless

A. Commandes à exécuter en tant que root (ou sudoer)

apt update 

Docker en mode rootless a besoin du packet uidmap, pour fonctionner. Installez le par le biais de la commande ci-dessous :

apt install uidmap 

Puis, créez l’utilisateur suivant :

adduser docker-for-prod

Ouvrez un autre terminal et connectez vous avec l’utilisateur docker-for-prod

su docker-for-prod

B. Commandes à exécuter par le biais de l’utilisateur non privilégié docker-for-prod

Vérifiez si votre utilisateur docker-for-prod a été automatiquement ajouté au contrôleur du gestionnaire de connexion systemd (loginctl) :

ls /var/lib/systemd/linger

Si celui-ci n’est pas présent, ajoutez votre utilisateur manuellement au contrôleur à l’aide de la commande suivante :

loginctl enable-linger docker-for-prod

Note : Pour plus d’informations concernant loginctl, libre à vous d’utiliser vos doigts et votre cerveau pour taper votre meilleure requête sur votre moteur de recherche favoris.^^

Vérifiez que la commande a bien été prise en compte en saisissant de nouveau la commande suivante :

ls /var/lib/systemd/linger

Si tout est ok, de votre côté, connectez vous en SSH à votre machine hôte, afin :

  • D’installer docker en mode rootless
  • D’interagir avec la commande systemctl, et d’autres composants sous-jacent nécessitant d’être connectés en SSH. (Je ne m’en rappel plus ^^)

Ouvrez donc un autre terminal, et connectez vous en ssh à cette même machine. (Même si ça peut paraître bizarre, vous avez besoin de faire ça pour actualiser le processus loginctl):

ssh [email protected]

Lancez l’installation de docker Rootless, par l’intermédiaire de la commande curl suivante :

curl -fsSl https://get.docker.com/rootless | sh
Capture de la sortie de la commande exécutée ci-dessus. (Partie 1)
Capture de la sortie de la commande exécutée ci-dessus. (Partie 2)

Maintenant que docker Rootless est installé, nous devons encore passer par quelques étapes de configuration.

Insérez les deux variables globales (telles quelles) ci-dessous dans votre fichier .bashrc (ou .zshrc etc., si-vous avez un autre shell que bash)

nano ~/.bashrc
# Dans le cas ou votre shell est zsh 
nano ~/.zshrc
export PATH=/home/docker-for-prod/bin:$PATH
export DOCKER_HOST=unix:///run/user/1001/docker.sock

Enregistrez les modifications, puis « sourcer » (comprendre : recharger, regénérer) votre shell courant.

source .bashrc
# OU 
source .zshrc

Démarrez ensuite docker et par la même occasion activez le démarrage du service au lancement de l’OS :

systemctl --user start docker
systemctl --user enable docker

IV. Test

Afin de tester si docker Rootless est bel et bien installé, instanciez un conteneur :

docker run -d alpine

Comme vous pouvez le constatez, docker-for-prod (qui est un user non privilégié) peut maintenant exécuter des conteneurs en mode Rootless.

Comme on est jamais assez prudent, redémarrez votre machine hôte, et vérifiez que vous pouvez utiliser de nouveau docker avec l’utilisateur prévu à cet effet :

docker-for-prod

Voilà, c’est tout pour cette fois-ci. Je vous laisse avec cette phrase (à méditer ^^)

A. L’article résumé en une phrase :

In rootless mode, root inside the container is not the same root as the host.

++

Geoffrey


Geoffrey Sauvageot-Berland

Ingénieur diplômé par l’état en Informatique et Cybersécurité. Généraliste, à l'origine administrateur systèmes et réseaux, j’occupe actuellement un poste d’auditeur en sécurité offensive. J’apprécie également la programmation/automatisation. Fondateur du blog : "Le Guide du SecOps", anciennement "Le Guide du SysOps"