meta données pour cette page
docker rootless sous ubuntu
Date | août 2023 |
---|---|
2024/07/31 | |
Temps | 10 minutes |
Difficulté | ★★☆☆☆ |
Type | how-to |
OS | ✓ Ubuntu GNU/Linux 24.04 LTS «noble numbat» |
✓ Ubuntu GNU/Linux 22.04 LTS «jammy jellyfish» | |
cible | sysadmins tout venant |
Références | docker : rootless (anglais) |
docker : installation sur ubuntu (anglais) | |
docker : installation (anglais) | |
github : Générer une clé ssh et l'ajouter à l'agent | |
digital ocean: configurer une authentication par clé ssh |
Le plus simple est de suivre les documentations citées en référence.
Mais j'ai noté un ou deux trucs. Ici, un résumé.
Commandes à passer sous le compte root
Pour économiser mes petits doigts, je ne tape sudo qu'une seule fois, pour devenir root. Si vous ne faites pas cela, vous préfixerez les commandes par sudo quand il le faudra.
sudo -i
Créer un utilisateur non privilégié
Utilisateur système, volontairement sans sudo et à mot de passe bloqué. Connexion uniquement via ssh et des clés.
- Création du compte système, ajout dans
/etc/subuid
et/etc/subgid
.nouveauCompte=dockeruser adduser --system --gecos "Docker rootless account" --group \ --home /home/$nouveauCompte --shell /bin/bash $nouveauCompte chpasswd -e <<<"${nouveauCompte}:*" && IFS=: read _ base taille < <( sort -b -t: -k 2,2n /etc/subuid | tail -1 ) && echo ${nouveauCompte}:$(( base + taille )):65536 >> /etc/subuid && IFS=: read _ base taille < <( sort -b -t: -k 2,2n /etc/subgid | tail -1 ) && echo ${nouveauCompte}:$(( base + taille )):65536 >> /etc/subgid
- Copie des clés ssh autorisées de root (très personnel et donc très optionnel). M'enfin, comme mot de passe est verrouillé, il faudra bien des clés ssh autorisées… Copiez les votres, quoi1).
install -d -m 0700 /home/${nouveauCompte}/.ssh cp -a /root/.ssh/authorized_keys /home/${nouveauCompte}/.ssh
- Préconfigurer le démon docker rootless avec un fichier daemon.json. Là encore c'est très personnel – et donc très optionnel – mais ça donne une idée de ce qu'on peut faire facilement.
install -d /home/${nouveauCompte}/.config/docker cat > /home/${nouveauCompte}/.config/docker/daemon.json <<'EOH' { "default-address-pools": [ { "base": "10.14.0.0/16", "size": 24 } ], "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } } EOH
- Et finalement, corriger les propriétaires et groupes des fichiers.
chown -hR ${nouveauCompte}: /home/${nouveauCompte}
Installation des commandes docker
Supprimer toute trace de docker qui n'est pas celui livré par docker soi même.
for pkg in \ docker.io docker-doc docker-compose docker-compose-v2 \ podman-docker containerd runc \ ; do apt-get purge $pkg done
Et puis installation
dpkg -l dbus-user-session | grep -q ^.i || sudo apt-get install dbus-user-session dpkg -l uidmap | grep -q ^.i || sudo apt-get install uidmap apt-get install ca-certificates curl gnupg install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc echo \ "deb [arch=$(dpkg --print-architecture) \ signed-by=/etc/apt/keyrings/docker.asc] \ https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null apt-get update apt-get install docker-ce docker-ce-cli containerd.io \ docker-buildx-plugin docker-compose-plugin
Docker est maintenant installé. Pour l'instant, en mode normal.
Préparation du mode rootless
Pour qu'on puisse utiliser les port réservés, il faut utiliser une et une seule des deux méthodes présentées ci-dessous.
- 1ère Alternative, ma préférée.
Ajouter la capacitéCAP_NET_BIND_SERVICE
à l'exécutablerootlesskit
.setcap cap_net_bind_service=ep $(which rootlesskit)
- 2023 :
A priori, ce réglage est permanent et devrait résister aux mises à jour. mais c'est pas certain. CF réponse 92703 d'ask ubuntu et cette réponse sur unix & linux. - 2024 :
Ça résiste, sans souci.
- 2ème Alternative
Abaisser le numéro du premier port non privilégié.
On indique que les ports non privilégiés démarrent à 0, tout simplement. Mais dans ce cas, tout process peut utiliser les ports non privilégiés, pas seulement les conteneurs docker rootless.echo net.ipv4.ip_unprivileged_port_start=0 > /etc/sysctl.d/99-z-unprivileded-ports-for-all.conf sysctl --system
Passage en mode rootless
En préliminaire, arrêter tout service docker qui traînerait par là,
et installer le paquet docker-ce-rootless-extras
.
systemctl disable --now docker.service docker.socket apt-get install docker-ce-rootless-extras
S'assurer que docker sera démarré au boot
loginctl enable-linger $nouveauCompte
Devenir l'utilisateur non privilégié dockeruser et continuer
ssh $nouveauCompte@localhost
dockerd-rootless-setuptool.sh install
Cette commande crée et active le contexte docker rootless
. C'est parfait.
Avec cet utilisateur, on peut maintenant utiliser la commande docker,
comme si docker était installé de manière standard.
Vérification que ça fonctionne bien
dockeruser@pc:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES dockeruser@pc:~$
On va malgré tout ajouter la variable d'environnement DOCKER_HOST à .bashrc
. En effet certaines commandes tierces, tel docker-compose
2),
n'utilisent pas le contexte docker mais cette variable.
echo . $HOME/.bashrc > $HOME/.profile echo export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock >> ~/.bashrc
S'assurer que le service utilisateur est bien démarré automatiquement.
systemctl --user enable docker
Et voilà, c'est tout pour le compte dockeruser.
Utiliser
reboot
Et après un redémarrage, on doit avoir le démon dockerd qui fonctionne.
Sur une machine distante, ou sur la même machine avec un compte d'utilisateur ordinaire différent du compte dédié qu'on vient de créer, on peut créer un contexte docker et l'activer. L'activation est en fait un réglage de la commande docker. À un moment donné, pour un utilisateur donné, il ne peut y avoir qu'un seul contexte docker actif. On peut créer des centaines de contextes différents si besoin.
docker context create \ --docker host=ssh://dockeruser@docker-pc \ --description "rootless docker on docker-pc" \ docker-pc
docker context use docker-pc
Ensuite, tout est possible. Voilà une session d'exemple.
moi@monpc:~ (0) $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES moi@monpc:~ (0) $ docker run --rm busybox echo hello world! Unable to find image 'busybox:latest' locally latest: Pulling from library/busybox ec562eabd705: Pull complete Digest: sha256:9ae97d36d26566ff84e8893c64a6dc4fe8ca6d1144bf5b87b2b85a32def253c7 Status: Downloaded newer image for busybox:latest hello world! moi@monpc:~ (0) $ docker run --rm busybox echo hello world! hello world! moi@monpc:~ (0) $ docker run --name patience --rm busybox sleep infinity^Ccontext canceled moi@monpc:~ (1) $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7c15a6d3b253 busybox "sleep infinity" 48 seconds ago Up 22 seconds patience moi@monpc:~ (0) $ : "Ah ben ça alors, le ^C n'a tué que la commande locale" moi@monpc:~ (0) $ : "Et la commande docker continue à fonctionner" moi@monpc:~ (0) $ docker stop patience patience moi@monpc:~ (0) $ : Voyons le réseau, maintenant. Détachons un conteneur moi@monpc:~ (0) $ : qui ne fait rien et allons voir. moi@monpc:~ (0) $ docker run --name patience --rm -d busybox sleep infinity af3adee0ae4485eaa50f1c5bcb486d58effa6df92528eb0e23aa85569bc3dda9 moi@monpc:~ (0) $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES af3adee0ae44 busybox "sleep infinity" 31 seconds ago Up 5 seconds patience moi@monpc:~ (0) $ docker exec -it patience sh/ # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:0a:0e:00:02 brd ff:ff:ff:ff:ff:ff inet 10.14.0.2/24 brd 10.14.0.255 scope global eth0 valid_lft forever preferred_lft forever / # exitmoi@monpc:~ (0) $ docker stop patience patience moi@monpc:~ (0) $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES moi@monpc:~ (0) $
docker-compose
est toujours vraiment nécessaire ? En effet, on peut utiliser docker compose ...