meta données pour cette page
  •  

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

envrac:docker-rootless [2024/08/16 17:25] (Version actuelle)
ztrulphcs créée
Ligne 1: Ligne 1:
 +====== 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 : [[https://docs.docker.com/engine/security/rootless/|rootless]] (anglais)  |
 +^ :::         | docker : [[https://docs.docker.com/engine/install/ubuntu/|installation sur ubuntu]] (anglais)  |
 +^ :::         | docker :  [[https://docs.docker.com/engine/install/|installation]] (anglais)  |
 +| :::         | github : [[https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent|Générer une clé ssh et l'ajouter à l'agent]]  |
 +| :::         | digital ocean: [[https://www.digitalocean.com/community/tutorials/how-to-configure-ssh-key-based-authentication-on-a-linux-server-fr|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.
 +
 +<code bash>
 +sudo -i
 +</code>
 +
 +===== 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''.<code bash>
 +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 
 +</code>
 +  - 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, quoi((En cas de manque de connaissances sur le sujet, mettez un mot de passe à cet utilisateur, ou vous pouvez également lire les deux dernières références citées dans le cartouche ce cet article.)).<code bash>
 +install -d -m 0700 /home/${nouveauCompte}/.ssh
 +cp -a /root/.ssh/authorized_keys /home/${nouveauCompte}/.ssh
 +</code>
 +  - 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.<code bash>
 +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
 +</code>
 +  - Et finalement, corriger les propriétaires et groupes des fichiers.<code bash>
 +chown -hR ${nouveauCompte}: /home/${nouveauCompte}
 +</code>
 +
 +
 +===== Installation des commandes docker =====
 +
 +
 +Supprimer toute trace de docker qui n'est pas celui livré par docker soi même.
 +
 +<code bash>
 +for pkg in \
 +    docker.io docker-doc docker-compose docker-compose-v2 \
 +    podman-docker containerd runc \
 +; do
 +  apt-get purge $pkg
 +done
 +</code>
 +
 +Et puis installation
 +<code bash>
 +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
 +</code>
 +
 +
 +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<sup>ère</sup> Alternative, ma préférée.\\ Ajouter la capacité ''CAP_NET_BIND_SERVICE'' à l'exécutable ''rootlesskit''.<code bash>
 +setcap cap_net_bind_service=ep $(which rootlesskit)
 +</code>
 +    * 2023 :\\ A priori, ce réglage est permanent et devrait résister aux mises à jour. mais c'est pas certain. CF [[https://askubuntu.com/a/92703|réponse 92703]] d'//ask ubuntu// et [[https://unix.stackexchange.com/questions/283366/linux-file-capabilities-are-lost-when-i-modify-the-file-is-this-expected-behavi/283408#283408|cette réponse]] sur //unix & linux//.
 +    * 2024 :\\ Ça résiste, sans souci.
 +  - 2<sup>ème</sup> 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//.<code>
 +echo net.ipv4.ip_unprivileged_port_start=0 > /etc/sysctl.d/99-z-unprivileded-ports-for-all.conf
 +sysctl --system
 +</code>
 +
 +===== 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''.
 +<code bash>
 +systemctl disable --now docker.service docker.socket
 +apt-get install docker-ce-rootless-extras
 +</code>
 +
 +==== S'assurer que docker sera démarré au boot ====
 +
 +<code bash>
 +loginctl enable-linger $nouveauCompte
 +</code>
 +
 +==== Devenir l'utilisateur non privilégié dockeruser et continuer ====
 +
 +<code bash>
 +ssh  $nouveauCompte@localhost
 +</code>
 +
 +<code bash>
 +dockerd-rootless-setuptool.sh install
 +</code>
 +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.
 +
 +++++détails si ça vous intéresse|
 +<cli>
 +dockeruser@pc:~$ dockerd-rootless-setuptool.sh install
 +[INFO] Creating /home/dockeruser/.config/systemd/user/docker.service
 +[INFO] starting systemd service docker.service
 ++ systemctl --user start docker.service
 ++ sleep 3
 ++ systemctl --user --no-pager --full status docker.service
 +● docker.service - Docker Application Container Engine (Rootless)
 +     Loaded: loaded (/home/dockeruser/.config/systemd/user/docker.service; disabled; preset: enabled)
 +     Active: active (running) since Wed 2024-07-31 18:18:23 CEST; 3s ago
 +       Docs: https://docs.docker.com/go/rootless/
 +   Main PID: 7091 (rootlesskit)
 +      Tasks: 40
 +     Memory: 40.3M (peak: 41.4M)
 +        CPU: 586ms
 +     CGroup: /user.slice/user-112.slice/user@112.service/app.slice/docker.service
 +             ├─7091 rootlesskit --state-dir=/run/user/112/dockerd-rootless --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run --propagation=rslave /usr/bin/dockerd-rootless.sh
 +             ├─7102 /proc/self/exe --state-dir=/run/user/112/dockerd-rootless --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run --propagation=rslave /usr/bin/dockerd-rootless.sh
 +             ├─7127 slirp4netns --mtu 65520 -r 3 --disable-host-loopback --enable-sandbox --enable-seccomp 7102 tap0
 +             ├─7134 dockerd
 +             └─7154 containerd --config /run/user/112/docker/containerd/containerd.toml
 +
 +Jul 31 18:18:23 pc dockerd-rootless.sh[7134]: time="2024-07-31T18:18:23.544446299+02:00" level=warning msg="WARNING: No io.weight support"
 +Jul 31 18:18:23 pc dockerd-rootless.sh[7134]: time="2024-07-31T18:18:23.544458281+02:00" level=warning msg="WARNING: No io.weight (per device) support"
 +Jul 31 18:18:23 pc dockerd-rootless.sh[7134]: time="2024-07-31T18:18:23.544468189+02:00" level=warning msg="WARNING: No io.max (rbps) support"
 +Jul 31 18:18:23 pc dockerd-rootless.sh[7134]: time="2024-07-31T18:18:23.544480578+02:00" level=warning msg="WARNING: No io.max (wbps) support"
 +Jul 31 18:18:23 pc dockerd-rootless.sh[7134]: time="2024-07-31T18:18:23.544489911+02:00" level=warning msg="WARNING: No io.max (riops) support"
 +Jul 31 18:18:23 pc dockerd-rootless.sh[7134]: time="2024-07-31T18:18:23.544499485+02:00" level=warning msg="WARNING: No io.max (wiops) support"
 +Jul 31 18:18:23 pc dockerd-rootless.sh[7134]: time="2024-07-31T18:18:23.544546115+02:00" level=info msg="Docker daemon" commit=cc13f95 containerd-snapshotter=false storage-driver=overlay2 version=27.1.1
 +Jul 31 18:18:23 pc dockerd-rootless.sh[7134]: time="2024-07-31T18:18:23.544688024+02:00" level=info msg="Daemon has completed initialization"
 +Jul 31 18:18:23 pc dockerd-rootless.sh[7134]: time="2024-07-31T18:18:23.596819194+02:00" level=info msg="API listen on /run/user/112/docker.sock"
 +Jul 31 18:18:23 pc systemd[4564]: Started docker.service - Docker Application Container Engine (Rootless).
 ++ DOCKER_HOST=unix:///run/user/112/docker.sock /usr/bin/docker version
 +Client: Docker Engine - Community
 + Version:           27.1.1
 + API version:       1.46
 + Go version:        go1.21.12
 + Git commit:        6312585
 + Built:             Tue Jul 23 20:00:07 2024
 + OS/Arch:           linux/arm64
 + Context:           default
 +
 +Server: Docker Engine - Community
 + Engine:
 +  Version:          27.1.1
 +  API version:      1.46 (minimum version 1.24)
 +  Go version:       go1.21.12
 +  Git commit:       cc13f95
 +  Built:            Tue Jul 23 20:00:07 2024
 +  OS/Arch:          linux/arm64
 +  Experimental:     false
 + containerd:
 +  Version:          1.7.19
 +  GitCommit:        2bf793ef6dc9a18e00cb12efb64355c2c9d5eb41
 + runc:
 +  Version:          1.7.19
 +  GitCommit:        v1.1.13-0-g58aa920
 + docker-init:
 +  Version:          0.19.0
 +  GitCommit:        de40ad0
 + rootlesskit:
 +  Version:          2.0.2
 +  ApiVersion:       1.1.1
 +  NetworkDriver:    slirp4netns
 +  PortDriver:       builtin
 +  StateDir:         /run/user/112/dockerd-rootless
 + slirp4netns:
 +  Version:          1.2.1
 +  GitCommit:        09e31e92fa3d2a1d3ca261adaeb012c8d75a8194
 ++ systemctl --user enable docker.service
 +Created symlink /home/dockeruser/.config/systemd/user/default.target.wants/docker.service → /home/dockeruser/.config/systemd/user/docker.service.
 +[INFO] Installed docker.service successfully.
 +[INFO] To control docker.service, run: `systemctl --user (start|stop|restart) docker.service`
 +[INFO] To run docker.service on system startup, run: `sudo loginctl enable-linger dockeruser`
 +
 +[INFO] Creating CLI context "rootless"
 +Successfully created context "rootless"
 +[INFO] Using CLI context "rootless"
 +Current context is now "rootless"
 +
 +[INFO] Make sure the following environment variable(s) are set (or add them to ~/.bashrc):
 +export PATH=/usr/bin:$PATH
 +
 +[INFO] Some applications may require the following environment variable too:
 +export DOCKER_HOST=unix:///run/user/112/docker.sock
 +
 +dockeruser@pc:~$ 
 +</cli>
 +++++
 +
 +Vérification que ça fonctionne bien
 +<cli>
 +dockeruser@pc:~$ docker ps -a
 +CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
 +dockeruser@pc:~$ 
 +</cli>
 +
 +On va malgré tout ajouter la variable d'environnement DOCKER_HOST à ''.bashrc''. En effet certaines commandes tierces, tel ''docker-compose''((Maintenant que la commande compose est un plugin de docker, est-ce que ''docker-compose'' est toujours vraiment nécessaire ? En effet, on peut utiliser <code bash>docker compose ...</code>)),
 +n'utilisent pas le contexte docker mais cette variable.
 +<code bash>
 +echo . $HOME/.bashrc > $HOME/.profile
 +echo export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock >> ~/.bashrc
 +</code>
 +
 +S'assurer que le service utilisateur est bien démarré automatiquement.
 +
 +<code bash>
 +systemctl --user enable docker
 +</code>
 +
 +Et voilà, c'est tout pour le compte dockeruser.
 +===== Utiliser =====
 +
 +<code bash>
 +reboot
 +</code>
 +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.
 +
 +<code bash>
 +docker context create \
 +       --docker host=ssh://dockeruser@docker-pc \
 +       --description "rootless docker on docker-pc" \
 +       docker-pc
 +</code><code bash>
 +docker context use docker-pc
 +</code>
 +
 +Ensuite, tout est possible. Voilà une session d'exemple.
 +<cli prompt="/^.*[$] /">
 +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
 +<cli prompt=/^/>
 +^C
 +</cli>
 +context 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
 +<cli prompt='# ' continue=none>
 +/ # 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
 +/ # exit
 +</cli>
 +moi@monpc:~ (0) $ docker stop patience
 +patience
 +moi@monpc:~ (0) $ docker ps -a
 +CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
 +moi@monpc:~ (0) $ 
 +</cli>
 +