とりあえずは https://wiki.archlinux.org/title/Docker#Rootless_Docker_daemon に従えばインストールできて普通に動く。コンテナ側で root ユーザーが作ったファイルのオーナーが自分になってくれるのがとても助かる。
/etc/subuid
, /etc/subgid
は両方とも以下としている。自分で決めたのか、docker-rootless-extras
が設定してくれたのかは覚えてない。
taiki:100000:65536
https://docs.docker.com/engine/security/rootless/#best-practices
~/.config/docker/daemon.json
何もしないとこんなエラーが出る
Error response from daemon: driver failed programming external connectivity on endpoint xxxx (d822ea73671d589020b511af00be5764d13004b4de9b6f838c4615c51e53bbcd): failed to bind port 0.0.0.0:443/tcp: Error starting userland proxy: error while calling PortManager.AddPort(): cannot expose privileged port 443, you can add 'net.ipv4.ip_unprivileged_port_start=443' 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:443: bind: permission denied
error: Recipe `up` failed on line 103 with exit code 1
sysctl で 443 を unprivilege にするのは怖いから setcap する。
❯❯ getcap /usr/sbin/rootlesskit
❯❯ sudo setcap cap_net_bind_service+ep /usr/sbin/rootlesskit
❯❯ getcap /usr/sbin/rootlesskit
/usr/sbin/rootlesskit cap_net_bind_service=ep
ユーザー権限で動いてるから $XDG_RUNTIME_DIR/docker.sock
にある。compose.yaml は大体固定でパスが書かれてたりするから、そのへんは何とかする。
何もしないと connection refused になる。
この辺を参考にする
- https://stackoverflow.com/questions/72500740/how-to-access-localhost-on-rootless-docker/74979409
- https://zenn.dev/gladevise/articles/access-localhost-from-docker-container
以下のどっちかになるっぽい
DOCKERD_ROOTLESS_ROOTLESSKIT_DISABLE_HOST_LOOPBACK=false
を設定する- セキュリティ上の理由で無効になってるみたいポートが限定できればいいのにね。
- nsenter と socat でコンテナからの通信を sock ファイル経由でホストのポートに転送する
セキュリティ的によろしくはないけど面倒だから host loopback を有効にする方向で
dockerd-rootless.sh
には以下のように書いてある。slirp4netns
の場合は 10.0.2.2 に接続できるようになるのだそう。
# * DOCKERD_ROOTLESS_ROOTLESSKIT_DISABLE_HOST_LOOPBACK=(true|false): prohibit connections to 127.0.0.1 on the host (including via 10.0.2.2, in the case of slirp4netns). Defaults to "true".
このアドレスについての slirp4netns のドキュメントは以下:
https://github.com/rootless-containers/slirp4netns/blob/master/slirp4netns.1.md
まず host loopback を有効にする
❯❯ cat ~/.config/systemd/user/docker.service.d/override.conf
[Service]
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_DISABLE_HOST_LOOPBACK=false"
これだけだと、host-gateway
は 172.17.0.1 (docker network の gateway address) のまま。
❯❯ docker run -it --add-host host.docker.internal:host-gateway busybox cat /etc/hosts | grep -e 'host.docker.internal'
172.17.0.1 host.docker.internal
~/.config/docker/daemon.json
に host-gateway-ips
を設定する。
❯❯ cat ~/.config/docker/daemon.json
{
"host-gateway-ips": ["10.0.2.2"]
}
そうすると 10.0.2.2 になる。
❯❯ docker run -it --add-host host.docker.internal:host-gateway busybox cat /etc/hosts | grep -e 'host.docker.internal'
10.0.2.2 host.docker.internal
これでホスト側に繋がるようになる。
❯❯ busybox httpd -p 9999 -h ~/tmp/
❯❯ docker run -it --add-host host.docker.internal:host-gateway busybox wget -O- http://host.docker.internal:9999/a.md | wc -l
804