Rootless Docker とは
Rootless モード(Rootless mode)は Docker デーモンとコンテナを root 以外のユーザが実行できるようにするもので、デーモンやコンテナ・ランタイムにおける潜在的な脆弱性を回避します。
Docker 公式ドキュメント
今回の環境
- Ubuntu Server 20.04 on VMware ESXi
いざ挑戦
まずは事前準備
uidmap 導入
ホスト上に newuidmap と newgidmap のインストールが必要です。
とのことなので、インストールしておきます。
$ sudo apt install -y uidmap
これをインストールしていないと Docker をインストールする際に
# Installing stable version 19.03.12
# Missing system requirements. Please run following commands to
# install the requirements and run this installer again.
# Alternatively iptables checks can be disabled with SKIP_IPTABLES=1
cat <<EOF | sudo sh -x
apt-get install -y uidmap
EOF
と言われるので入れ忘れないようにしましょう。(体験談)
UID/GID 確認
/etc/subuid と /etc/subgid はユーザに対して、少なくともサブオーディネイト UID/GID を 65,536 含むべきです。
とのことなので確認しておきましょう。
$ grep ^$(whoami): /etc/subuid
dev:100000:65536
$ grep ^$(whoami): /etc/subgid
dev:100000:65536
65536
が両方に含まれていれば OK です。
インストール
ワンライナーで導入できるのは通常の Docker と同じです。
$ curl -fsSL get.docker.com/rootless | sh
# Installing stable version 19.03.12
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 57.9M 100 57.9M 0 0 18.0M 0 0:00:03 0:00:03 --:--:-- 18.0M
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 18.3M 100 18.3M 0 0 6245k 0 0:00:03 0:00:03 --:--:-- 6245k
# starting systemd service
● docker.service - Docker Application Container Engine (Rootless)
Loaded: loaded (/home/dev/.config/systemd/user/docker.service; disabled; vendor preset: enabled)
Active: active (running) since Sat 2020-07-25 08:07:23 UTC; 21ms ago
Docs: https://docs.docker.com
Main PID: 45635 (rootlesskit)
CGroup: /user.slice/user-1000.slice/user@1000.service/docker.service
tq45635 rootlesskit --net=vpnkit --mtu=1500 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run /home/dev/bin/dockerd-rootless.sh --experimental --storage-driver=overlay2
tq45647 /proc/self/exe --net=vpnkit --mtu=1500 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run /home/dev/bin/dockerd-rootless.sh --experimental --storage-driver=overlay2
mq45656 newgidmap 45647 0 1000 1 1 100000 65536
Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + which slirp4netns
Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + [ -z ]
Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + which vpnkit
Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + net=vpnkit
Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + [ -z ]
Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + mtu=1500
Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + [ -z ]
Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + _DOCKERD_ROOTLESS_CHILD=1
Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + export _DOCKERD_ROOTLESS_CHILD
Jul 25 08:07:23 docker dockerd-rootless.sh[45635]: + exec rootlesskit --net=vpnkit --mtu=1500 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run /home/dev/bin/dockerd-rootless.sh --experimental --storage-driver=overlay2
Client: Docker Engine - Community
Version: 19.03.12
API version: 1.40
Go version: go1.13.10
Git commit: 48a66213fe
Built: Mon Jun 22 15:42:53 2020
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.12
API version: 1.40 (minimum version 1.12)
Go version: go1.13.10
Git commit: 48a66213fe
Built: Mon Jun 22 15:49:35 2020
OS/Arch: linux/amd64
Experimental: true
containerd:
Version: v1.2.13
GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683
# Docker binaries are installed in /home/dev/bin
# WARN: dockerd is not in your current PATH or pointing to /home/dev/bin/dockerd
# Make sure the following environment variables are set (or add them to ~/.bashrc):
export PATH=/home/dev/bin:$PATH
export DOCKER_HOST=unix:///run/user/1000/docker.sock
#
# To control docker service run:
# systemctl --user (start|stop|restart) docker
#
これでインストールが完了しました。
ですがこのままでは docker
コマンドは使えません。
※パスが通っている場所にインストールしたわけではないため
docker
コマンドを使えるようにするために環境変数に追加します。
$ export PATH=/home/dev/bin:$PATH
$ export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
実際に確認してみましょう。
$ docker info
Client:
Debug Mode: false
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 1
Server Version: 19.03.12
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: false
Logging Driver: json-file
Cgroup Driver: none
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 7ad184331fa3e55e52b890ea95e65ba581ae3429
runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd
init version: fec3683
Security Options:
seccomp
Profile: default
rootless
Kernel Version: 5.4.0-42-generic
Operating System: Ubuntu 20.04.1 LTS
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 7.774GiB
Name: docker
ID: NURI:7LP5:IHUJ:VSSV:6E5W:VMLS:4D52:X5EJ:CB24:CDJ2:OMAO:LMWB
Docker Root Dir: /home/dev/.local/share/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: true
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
Product License: Community Engine
docker
コマンドが使えていることと、 Security Options
に rootless
が含まれている点が確認できました。
使ってみる
とりあえず Nginx
を動かしてみましょう。
$ docker run -dP --name nginx nginx
11cd14bb3bf8d4b99aa46be825bfd7f51143bc578e68ef265f3add1baa0b19ed
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
11cd14bb3bf8 nginx "/docker-entrypoint.…" 19 seconds ago Up 18 seconds 0.0.0.0:32768->80/tcp nginx
$ curl -s localhost:32768 | head -n 5
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
ポートフォワードもしっかり動いていることが確認できました。
$ ps -aux | grep docker
dev 1519 0.0 0.0 112232 6856 ? Ssl 10:18 0:00 rootlesskit --net=vpnkit --mtu=1500 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run /home/dev/bin/dockerd-rootless.sh --experimental --storage-driver=overlay2
dev 1528 7.4 0.1 112872 12060 ? Sl 10:18 0:05 /proc/self/exe --net=vpnkit --mtu=1500 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run /home/dev/bin/dockerd-rootless.sh --experimental --storage-driver=overlay2
dev 1562 20.5 0.8 1638352 67892 ? Sl 10:18 0:14 dockerd --experimental --storage-driver=overlay2
dev 1583 1.1 0.2 1241920 23784 ? Ssl 10:18 0:00 containerd --config /run/user/1000/docker/containerd/containerd.toml --log-level info
dev 1875 0.0 0.0 106976 4780 ? Sl 10:19 0:00 /home/dev/bin/rootlesskit-docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 32768 -container-ip 172.17.0.2 -container-port 80
dev 1880 0.0 0.0 103372 2364 ? Sl 10:19 0:00 docker-proxy -container-ip 172.17.0.2 -container-port 80 -host-ip 127.0.0.1 -host-port 32768 -proto tcp
dev 1891 0.0 0.0 108872 4604 ? Sl 10:19 0:00 containerd-shim -namespace moby -workdir /home/dev/.local/share/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/2f657a2a65b754ff9bd59254f1cd36b745c3f2679aa795c474e6ba29ead4e560 -address /run/user/1000/docker/containerd/containerd.sock -containerd-binary /home/dev/bin/containerd -runtime-root /run/user/1000/docker/runtime-runc
dev 1976 0.0 0.0 5192 740 pts/0 S+ 10:20 0:00 grep --color=auto docker
また、 root
ユーザーではなく dev
ユーザーで実行していることも確認できました。