概要
現在、EC2上でDocker CEを利用している。先日↓の記事を見かけたので、Rootless Dockerへの移行(といっても、Volumeのみ)を試してみる。
RootlessモードでDockerをより安全にする [DockerCon発表レポート] – nttlabs – Medium
Rootless Docker?
Rootlessモードは,Dockerデーモン及びコンテナを,非rootユーザで実行する技術です.Rootlessモードを用いることにより,万一Dockerに脆弱性や設定ミスがあっても,攻撃者にホストのroot権限を奪取されることを防ぐことが出来ます.
参考: RootlessモードでDockerをより安全にする [DockerCon発表レポート] – nttlabs – Medium
Amazon Linuxでいうところのec2-user
ユーザだけで、Dockerデーモンの起動からdockerコマンドの利用までできるということ。
普通にDockerを起動すると、root
ユーザでコンテナを起動する必要があるから、rootを乗っ取られる可能性がある。
よくある一般ユーザをdockerグループに属させて、一般ユーザでdockerコマンドを利用できるようにさせても、Docker自体はroot
ユーザで起動させているから、rootを乗っ取られる可能性がある。
Rootless Dockerは、一般ユーザだけで完結できるから、rootを取られる可能性が限りなく0に近づくってことですかね。
試した環境
少しOSやDocker CEが古いが...
[ec2-user@localhost ~]$ cat /etc/os-release
NAME="Amazon Linux AMI"
VERSION="2018.03"
ID="amzn"
ID_LIKE="rhel fedora"
VERSION_ID="2018.03"
PRETTY_NAME="Amazon Linux AMI 2018.03"
ANSI_COLOR="0;33"
CPE_NAME="cpe:/o:amazon:linux:2018.03:ga"
HOME_URL="http://aws.amazon.com/amazon-linux-ami/"
[ec2-user@localhost ~]$ docker version
Client:
Version: 18.06.1-ce
API version: 1.38
Go version: go1.10.3
Git commit: e68fc7a215d7133c34aa18e3b72b4a21fd0c6136
Built: Mon Mar 4 21:25:23 2019
OS/Arch: linux/amd64
Experimental: false
Server:
Engine:
Version: 18.06.1-ce
API version: 1.38 (minimum version 1.12)
Go version: go1.10.3
Git commit: e68fc7a/18.06.1-ce
Built: Mon Mar 4 21:26:49 2019
OS/Arch: linux/amd64
Experimental: false
移行前のコンテナ環境
まずは、移行を試す環境を作る。
docker volume create
でボリュームを作り、centos
コンテナにマウントさせて起動する。
起動したコンテナ上で、1GBほどのファイルを作っておく。
[root@localhost ~]# docker volume create test
test
[root@localhost ~]# docker run -itd -v test:/mnt centos
Unable to find image 'centos:latest' locally
latest: Pulling from library/centos
8ba884070f61: Pull complete
Digest: sha256:b5e66c4651870a1ad435cd75922fe2cb943c9e973a9673822d1414824a1d0475
Status: Downloaded newer image for centos:latest
d1256d1226bcd445616f13a0e73bbb322056c9151c7adbc7c7d84011e2afe4eb
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d1256d1226bc centos "/bin/bash" 7 seconds ago Up 6 seconds romantic_bell
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 9f38484d220f 8 weeks ago 202MB
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local test
[root@localhost ~]# docker exec -it romantic_bell bash
[root@d1256d1226bc /]# cd /mnt
[root@d1256d1226bc mnt]# dd if=/dev/zero of=zerofile bs=1024 count=1000000
1000000+0 records in
1000000+0 records out
1024000000 bytes (1.0 GB) copied, 2.46405 s, 416 MB/s
[root@d1256d1226bc mnt]# ls -lh
total 977M
-rw-r--r-- 1 root root 977M May 12 08:49 zerofile
[root@d1256d1226bc mnt]# exit
移行前準備
Rootless Dockerをインストール(Docker CEを削除)する前に、ホスト側から前項で作成したボリュームを退避させる。
退避前にコンテナも止めておく。
退避したボリュームは、Rootless Dockerを実行するユーザ、グループに予め変更しておく。
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d1256d1226bc centos "/bin/bash" 7 seconds ago Up 6 seconds romantic_bell
[root@localhost ~]# docker stop romantic_bell
romantic_bell
[root@localhost ~]# cp -rp /var/lib/docker/volumes /tmp/
[root@localhost ~]# chown -R ec2-user:ec2-user /tmp/volumes/
[root@localhost ~]# docker rm romantic_bell
romantic_bell
Docker CEのアンインストール
Rootless Dockerを入れる前に、Docker CEをアンインストールする。
アンインストールをしないと、何故かRootless DockerがDocker CEの/var/run/docker.sock
等を使って起動しなかった
[root@localhost ~]# yum -y remove docker
Loaded plugins: priorities, update-motd, upgrade-helper
Resolving Dependencies
--> Running transaction check
---> Package docker.x86_64 0:18.06.1ce-8.28.amzn1 will be erased
--> Finished Dependency Resolution
Dependencies Resolved
==============================================================================================================================================
Package Arch Version Repository Size
==============================================================================================================================================
Removing:
docker x86_64 18.06.1ce-8.28.amzn1 @amzn-updates 150 M
Transaction Summary
==============================================================================================================================================
Remove 1 Package
Installed size: 150 M
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Erasing : docker-18.06.1ce-8.28.amzn1.x86_64 1/1
Verifying : docker-18.06.1ce-8.28.amzn1.x86_64 1/1
Removed:
docker.x86_64 0:18.06.1ce-8.28.amzn1
Complete!
[root@localhost ~]#
Rootless Dockerのインストール&実行
インストールといっても、コマンド1つで終わるらしい。
[ec2-user@localhost ~]$ curl -fsSL https://get.docker.com/rootless | sh
# 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
curl -o /etc/yum.repos.d/vbatts-shadow-utils-newxidmap-epel-7.repo https://copr.fedorainfracloud.org/coprs/vbatts/shadow-utils-newxidmap/repo/epel-7/vbatts-shadow-utils-newxidmap-epel-7.repo
yum install -y shadow-utils46-newxidmap
EOF
パッケージが足りない。
[ec2-user@localhost ~]$ cat <<EOF | sudo sh -x
> curl -o /etc/yum.repos.d/vbatts-shadow-utils-newxidmap-epel-7.repo https://copr.fedorainfracloud.org/coprs/vbatts/shadow-utils-newxidmap/repo/epel-7/vbatts-shadow-utils-newxidmap-epel-7.repo
> yum install -y shadow-utils46-newxidmap
> EOF
~省略~
[ec2-user@localhost ~]$ curl -fsSL https://get.docker.com/rootless | sh
Could not find records for the current user ec2-user from /etc/subuid . Please make sure valid subuid range is set there.
For example:
echo "ec2-user:100000:65536" >> /etc/subuid
/etc/subuid
,/etc/subgid
がない。
そもそも見た記憶がない。作る。
[root@localhost ~]$ sudo su -
[root@localhost ~]# echo "ec2-user:1000:65536" >> /etc/subuid
[root@localhost ~]# echo "ec2-user:1000:65536" >> /etc/subgid
[root@localhost ~]# exit
[ec2-user@localhost ~]$ curl -fsSL https://get.docker.com/rootless | sh
# systemd not detected, dockerd daemon needs to be started manually
/home/ec2-user/bin/dockerd-rootless.sh --experimental --storage-driver vfs
# Docker binaries are installed in /home/ec2-user/bin
# WARN: dockerd is not in your current PATH or pointing to /home/ec2-user/bin/dockerd
# Make sure the following environment variables are set (or add them to ~/.bashrc):\n
export XDG_RUNTIME_DIR=/tmp/docker-500
export DOCKER_HOST=unix:///tmp/docker-500/docker.sock
言われた通りに、.bashrc
に追加する。
また、bin
ディレクトリもできていたので、合わせて追加する。
/tmp/docker-500
配下にdocker.sock
ができるので、嫌な場合はこれらの環境変数を変えておけばよさそう。
[ec2-user@localhost ~]$ echo "export XDG_RUNTIME_DIR=/tmp/docker-500" >> ~/.bashrc
[ec2-user@localhost ~]$ echo "export DOCKER_HOST=unix:///tmp/docker-500/docker.sock" >> ~/.bashrc
[ec2-user@localhost ~]$ echo 'PATH=$PATH:$HOME/bin' >> .bashrc
[ec2-user@localhost ~]$ source .bashrc
インストールが終わったので、言われたとおりにサーバを起動する。
起動し続けておく必要があるので、screen
で起動する。デタッチは、デフォルトはCtrl-a
押してd
[ec2-user@localhost ~]$ screen
[ec2-user@localhost ~]$ /home/ec2-user/bin/dockerd-rootless.sh --experimental --storage-driver vfs
INFO[2019-05-12T08:08:51.179358654Z] Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address
INFO[2019-05-12T08:08:51.330646070Z] Loading containers: done.
INFO[2019-05-12T08:08:51.344736419Z] Docker daemon commit=3998dff graphdriver(s)=vfs version=master-dockerproject-2019-05-11
INFO[2019-05-12T08:08:51.344855472Z] Daemon has completed initialization
INFO[2019-05-12T08:08:51.362135829Z] API listen on /tmp/docker-500/docker.sock
[detached]
[ec2-user@localhost ~]$
[ec2-user@localhost ~]$ docker version
Client:
Version: master-dockerproject-2019-05-11
API version: 1.40
Go version: go1.12.5
Git commit: 53fc2572
Built: Sat May 11 23:39:34 2019
OS/Arch: linux/amd64
Experimental: false
Server:
Engine:
Version: master-dockerproject-2019-05-11
API version: 1.40 (minimum version 1.12)
Go version: go1.12.5
Git commit: 3998dff
Built: Sat May 11 23:46:26 2019
OS/Arch: linux/amd64
Experimental: true
containerd:
Version: v1.2.6
GitCommit: 894b81a4b802e4eb2a91d1ce216b8817763c29fb
runc:
Version: 1.0.0-rc8
GitCommit: 425e105d5a03fabd737a126ad93d62a9eeede87f
docker-init:
Version: 0.18.0
GitCommit: fec3683
適当なコンテナを起動してみる
docker
コマンドはパスを通したので今までどおり使える。
[ec2-user@localhost ~]$ docker run -d -p 8080:80 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
743f2d6c1f65: Pull complete
6bfc4ec4420a: Pull complete
688a776db95f: Pull complete
Digest: sha256:23b4dcdf0d34d4a129755fc6f52e1c6e23bb34ea011b315d87e193033bcd1b68
Status: Downloaded newer image for nginx:latest
a26c026eddf0f0d92db01e6cd6984f83904ffc5b4d69dd245a3a88081cdc6db5
[ec2-user@localhost ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a26c026eddf0 nginx "nginx -g 'daemon of…" 4 seconds ago Up 3 seconds 0.0.0.0:8080->80/tcp xenodochial_khayyam
[ec2-user@localhost ~]$ curl http://localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[ec2-user@localhost ~]$
Rootless Docker動いた
ボリュームの移行
そもそもvolumes
ディレクトリはどこにあるのか。
[ec2-user@ip-172-31-47-41 ~]$ ll /tmp/docker-500/
total 12
drwx-----T 7 ec2-user ec2-user 4096 May 12 08:58 docker
-rw-r--r-T 1 ec2-user ec2-user 5 May 12 08:58 docker.pid
srw-rw---T 1 ec2-user 1496 0 May 12 08:58 docker.sock
drwx-----T 2 ec2-user ec2-user 4096 May 12 08:08 runc
[ec2-user@ip-172-31-47-41 ~]$ find . -name 'docker'
./.vim/plugged/ultisnips/docker
./.local/share/docker
~省略~
[ec2-user@ip-172-31-47-41 ~]$ ll .local/share/docker/
total 56
drwx------ 2 ec2-user ec2-user 4096 May 12 08:08 builder
drwx------ 4 ec2-user ec2-user 4096 May 12 08:08 buildkit
drwx------ 3 ec2-user ec2-user 4096 May 12 08:08 containerd
drwx------ 4 ec2-user ec2-user 4096 May 12 09:11 containers
-rw------- 1 ec2-user ec2-user 36 May 12 08:08 engine_uuid
drwx------ 3 ec2-user ec2-user 4096 May 12 08:08 image
drwxr-x--- 3 ec2-user ec2-user 4096 May 12 08:08 network
drwx------ 4 ec2-user ec2-user 4096 May 12 08:08 plugins
drwx------ 2 ec2-user ec2-user 4096 May 12 08:58 runtimes
drwx------ 2 ec2-user ec2-user 4096 May 12 08:08 swarm
drwx------ 2 ec2-user ec2-user 4096 May 12 09:11 tmp
drwx------ 2 ec2-user ec2-user 4096 May 12 08:08 trust
drwx------ 3 ec2-user ec2-user 4096 May 12 08:15 vfs
drwx------ 3 ec2-user ec2-user 4096 May 12 09:08 volumes
[ec2-user@ip-172-31-47-41 ~]$
ホームディレクトリの.local/share/docker
配下にあった
[ec2-user@ip-172-31-47-41 ~]$ ll .local/share/docker/volumes
total 24
-rw------- 1 ec2-user ec2-user 32768 May 12 09:08 metadata.db
メタデータがあるので、ディレクトリだけ移動
でも移動だけだと認識されないので、同名でdocker volume create
[ec2-user@localhost ~]$ mv /tmp/volumes/test ~/.local/share/docker/volume/
[ec2-user@localhost ~]$ docker volume ls
DRIVER VOLUME NAME
[ec2-user@localhost ~]$
[ec2-user@localhost ~]$ docker volume create test
test
[ec2-user@localhost ~]$ docker volume ls
DRIVER VOLUME NAME
local test
あとは、Docker CE
のときと同じようにコンテナを作成する。
[ec2-user@localhost ~]$ docker run -itd -v test:/mnt centos
Unable to find image 'centos:latest' locally
latest: Pulling from library/centos
8ba884070f61: Pull complete
Digest: sha256:b5e66c4651870a1ad435cd75922fe2cb943c9e973a9673822d1414824a1d0475
Status: Downloaded newer image for centos:latest
cfbadb0e2e67047bf25e23a2ce73835dfb9557e8341e4aead1cf658d69eacf9a
[ec2-user@localhost ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cfbadb0e2e67 centos "/bin/bash" About a minute ago Up About a minute jolly_fermi
[ec2-user@localhost ~]$
[ec2-user@localhost ~]$
[ec2-user@localhost ~]$ docker inspect jolly_fermi | grep volume
"Type": "volume",
"Source": "/home/ec2-user/.local/share/docker/volumes/test/_data",
[ec2-user@localhost ~]$ docker exec jolly_fermi /bin/ls /mnt -l
total 1000004
-rw-r--r-- 1 root root 1024000000 May 12 08:49 zerofile
[ec2-user@ip-172-31-47-41 ~]$ docker exec jolly_fermi bash -c "echo 'hello' >> /mnt/hello.txt"
[ec2-user@ip-172-31-47-41 ~]$ cat .local/share/docker/volumes/test/_data/hello.txt
hello
[ec2-user@ip-172-31-47-41 ~]$
どうやらボリュームの移行はちゃんとできたようだ
[参考]
moby/rootless.md at master · moby/moby
RootlessモードでDockerをより安全にする [DockerCon発表レポート] – nttlabs – Medium
最後に
気が向いたらdocker-compose
で作成したものも試しておきたい。