Les conteneurs rootless

Elements des stack

Isolation Fakeroot avec rootlesskit

exemples pris sur RootKit

On est root et on garde les variables d'env

(host)$ rootlesskit bash
(rootlesskit)# echo $USER
penguin
(rootlesskit)# echo $HOME
/home/penguin
(rootlesskit)# echo $XDG_RUNTIME_DIR
/run/user/1001

On peut protéger des espaces disques

(host)$ rootlesskit --copy-up=/etc bash
(rootlesskit)# rm /etc/resolv.conf
(rootlesskit)# vi /etc/resolv.conf

Comment créer un accès réseau

(host)$ rootlesskit --copy-up=/etc --copy-up=/run --net=slirp4netns --disable-host-loopback bash
(rootleesskit)# ip netns add foo

Pour aller plus loin, RTFM rootlesskit --help

on décortique rootlesskit

Ce qui est lancé par docker-rootless

rootlesskit \
  --state-dir=/run/user/1000/dockerd-rootless \
  # Le réseau \
  --net=slirp4netns \
  --mtu=65520 \
  --slirp4netns-sandbox=auto \
  --slirp4netns-seccomp=auto \
  --disable-host-loopback \
  --port-driver=builtin \
  # On fait une copie des fichiers de conf \
  --copy-up=/etc \
  --copy-up=/run \
  --propagation=rslave \
  /home/fccagou/src/docker/docker-rootless/dockerd-rootless.sh

state-dir, contient les éléments d'état

/run/user/1000/dockerd-rootless/
├── api.sock     # socket utilisée par rootlessctl
├── child_pid    # Pid du fork de rootlesskit
├── hosts        # Copie du /etc/hosts de l'hôte
├── lock         # lock posé par le fork de rootlesskit
└── resolv.conf  # Généré par rootlesskit

Avoir des infos avec rootlessctl

rootlessctl --socket /run/user/1000/dockerd-rootless/api.sock list-ports
ID    PROTO    PARENTIP    PARENTPORT    CHILDIP      CHILDPORT    
7     tcp4     0.0.0.0     5000          127.0.0.1    5000         
8     tcp6     ::          5000          ::1          5000         
11    tcp4     0.0.0.0     5080          127.0.0.1    5080         
12    tcp6     ::          5080          ::1          5080        

Schéma général

%%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%% flowchart style rootlesskit fill:#ddddff style network fill:none,stroke-dasharray: 5 5 rootlesskit --> slirp4ns rootlesskit --> port rootlesskit --> mount subgraph network slirp4ns port end subgraph mount localmount("/etc, /run") end

Le réseau avec slirp4ns

En rootless, slirp4ns fait actuellement l'hunanimité. Il utilise libslirp venant de qemu

# dans main.c
#define DEFAULT_CIDR ("10.0.2.0/24")
%%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%% flowchart style slirp4ns fill:none,stroke-dasharray: 5 5 style fork fill:#ffddff,stroke-dasharray: 5 5 style parent fill:#ffeeff,stroke-dasharray: 5 5 style child fill:#ffeeff,stroke-dasharray: 5 5 style network_namespace fill:#ffddff,stroke-dasharray: 5 5 style sendmsg fill:#ffddaa style recvmsg fill:#ffeeaa style loop fill:#aaaaff sendmsg([sendmsg]) -.tapfd.-> recvmsg([recvmsg]) subgraph slirp4ns direction TB socketpair --> fork{{fork}} fork --> child & parent end subgraph child user_namespace network_namespace end subgraph network_namespace tapc[tap] --> config_network --> sendmsg end subgraph config_network lo mac[@mac] ip[@ip] mtu netmask route end subgraph parent recvmsg --> tapp[tap] --> do_slirp["do_slirp(tapfd)"] do_slirp --> create_sandbox --> enable_seccomp do_slirp --> tapfd & create_slirp & create_api_socket loop((forever send/recv msg)) tapfd --> loop create_slirp --> loop create_api_socket --> loop end

Liens utils