LoginSignup
3
4

More than 3 years have passed since last update.

Docker とユーザー名前空間

Last updated at Posted at 2020-04-27

ユーザー名前空間は、Linux カーネルに実装されている機能。ユーザー名前空間内では、ホストOSとは独立した UID,GID を持つことができる機能になっている。Docker コンテナを立ち上げたときにデフォルトでは、コンテナ内は root ユーザーになっているが、この root ユーザーはホストOSの root ユーザーとは別のユーザーである。ユーザー名は一緒だがホストOSからは独立した Docker コンテナ内で定義された root ユーザーになっており、また、ユーザー名前空間内の UID,GID とホストOS上の UID,GID の間はマッピングによるひもづけが行われている。

ホストOSの root と Docker コンテナの root が別であることを手を動かしながら確かめて、ユーザー名前空間という機能を見てみる。

環境

  • ubuntu 18.04 (aws ec2 instance)

Docker の環境も整える。

$ sudo apt-get update
$ sudo apt-get install docker.io
$ sudo systemctl enable docker
$ docker --version
Docker version 19.03.6, build 369ce74a3c

手を動かして確かめてみる

ホストOSの root ユーザーで作成したファイルは、Docker コンテナの root ユーザーとユーザー名は一緒でも違う root ユーザーなので、Docker コンテナの root ユーザーからは見えないはずである。

# root ユーザーにチェンジ
$ sudo su -
$ id
uid=0(root) gid=0(root) groups=0(root)
$ echo "i am from host" > /tmp/file.txt
$ ls -l /tmp/file.txt
-rw-r--r-- 1 root root 15 Apr 27 03:05 /tmp/file.txt

dokcer デーモンは、--userns-remap=defaultを指定する。

注意
ここで--userns-remapを指定なしとした場合は、ホストOSの root ユーザーが作成するユーザー名前空間のユーザーと Docker コンテナ内の root ユーザーがマッピングされ、別のユーザーではあるが、わかりづらく、今回の確認方法では権限上は差異もないので、マッピングするユーザーを root 以外にしている。

$ sudo dockerd --userns-remap=default &

defaultが指定された場合のユーザーは、dockremapとなる。
このユーザー dockremap が Docker コンテナを立ち上げた場合は、dockremap が作成したユーザー名前空間内の root が Docker コンテナの root となる。

$ sudo docker pull alpine:3.9.6
$ sudo docker run -itd -v /tmp/:/shared/ --name tmp alpine:3.9.6
$ sudo docker exec -it tmp sh
$ id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
$ cat /tmp/file.txt
$ cat: can't open '/tmp/file.txt': No such file or directory

Docker コンテナでのidは root であり、uid=0となっている。しかし、これは ホストOSの root とは別で、あくまでもユーザー名前空間内での root になっている。/sharedは、ホストOSにマウントしているため、Docker コンテナとホストOSの root が同一であれば、参照はできるが、違うユーザーなのでNo such file or directoryとしてエラーが出ている。

Docker コンテナの root ユーザーは何?

dockremapがユーザー名前空間内に作成したUID=231072のユーザーであり、このユーザーが Docker コンテナ内では root にマッピングされている。

# ホストOSで /etc/subuid を見てみる
$ cat /etc/subuid
lxd:100000:65536
root:100000:65536
ubuntu:165536:65536
dockremap:231072:65536

/etc/subuidには、ユーザー名前空間を作成したときに、割り振る UID が書いてある。
ユーザー名:UID開始番号:範囲となっている。例えば、root ユーザーがユーザー名前空間を作成したときは、100000 ~ 165536 の範囲で UID が振られる。一番最初に振られる UID は、UID開始番号なので、さっき作成した Docker コンテナの root ユーザーは、231072 が振られている。

# ホストOSで ps コマンドをするとユーザー231072にたてられた sh が見える
$ ps aux | grep 231072
231072    5880  0.0  0.1   1596  1060 pts/0    Ss+  03:24   0:00 /bin/sh

ホストOSでは、UID は231072だが、ユーザー名前空間内では root であり、UID は 0になる。このホストOSの UID と Docker コンテナ内の UID のマッピングまで、ユーザー名前空間の機能である。

まとめ

Docker は難しい、終わり!

参考

https://gihyo.jp/admin/serial/01/linux_containers/0016?page=1
https://knowledge.sakura.ad.jp/5118/
https://linuxjm.osdn.jp/html/LDP_man-pages/man5/proc.5.html
Hacking and Securing Docker Containers (Udemy)

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4