Docker コンテナで Docker ホストのボリュームをマウントすると、パーミッションの問題が生じることがある。 これは、ホストで使っているユーザとコンテナで使っているユーザで UID と GID の不一致が起こるため。
今回は、それらの問題を解決する方法の一つとして Docker コンテナとホストで同じユーザを使う方法を試してみる。
具体的には、Docker ホストの /etc/passwd
と /etc/group
をコンテナからマウントしてしまう。
そのため、このやり方は Docker for Mac や Docker for Windows では使えない。
典型的なユースケースは、パッケージやライブラリといった実行環境はコンテナ内に隠蔽しつつ、その他はホストの環境をなるべく使い回したいというものだろう。
使った環境は次の通り。
$ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=18.04 DISTRIB_CODENAME=bionic DISTRIB_DESCRIPTION="Ubuntu 18.04.3 LTS" $ uname -r 4.15.0-62-generic
コンテナとホストでユーザが異なる場合の問題点について
まずはコンテナとホストでユーザの UID と GID が異なる場合の問題点について見ておく。
例えば Docker ホストでは次のユーザを使っているとする。
$ id uid=1000(vagrant) gid=1000(vagrant) groups=1000(vagrant)
試しに、カレントディレクトリにファイルを作っておこう。
$ echo "Hello, World" > greet.txt $ ls -lF total 4 -rw-rw-r-- 1 vagrant vagrant 13 Sep 19 09:10 greet.txt
続いて Docker コンテナを起動する。
カレントワーキングディレクトリを /mnt/working
にマウントしておく。
$ sudo docker run \ --rm \ -v $(pwd):/mnt/working \ -it busybox
この状態ではコンテナに root ユーザでログインしている。
# whoami root # id uid=0(root) gid=0(root) groups=10(wheel)
マウントしたディレクトリに移動してファイルを作ってみる。
# cd /mnt/working/ # echo "Hello, World" > greet-docker-root.txt
ディレクトリにあるファイルを確認すると、次のようになっている。
自分で作ったファイルは root:root
の権限がついている。
先ほど Docker ホストから作ったファイルは 1000:1000
という UID と GID がそのまま表示されている。
これは Docker コンテナ側で、それらの ID を持ったユーザが存在しないために起きている。
# ls -lF total 8 -rw-r--r-- 1 root root 13 Sep 19 09:14 greet-docker-root.txt -rw-rw-r-- 1 1000 1000 13 Sep 19 09:10 greet.txt
Docker ホスト側でも同様に ls
してみた結果は次の通り。
こちらでも Docker コンテナで作ったファイルは root:root
となっている。
ホストで作ったファイルは現在のユーザの権限がついている。
$ ls -lF total 8 -rw-r--r-- 1 root root 13 Sep 19 09:14 greet-docker-root.txt -rw-rw-r-- 1 vagrant vagrant 13 Sep 19 09:10 greet.txt
念のため、root 以外でも異なる UID と GID を持ったユーザを作って確認しておこう。
次の Dockerfile では example
ユーザが 10000:10000
という UID と GID を持つようにしてある。
$ cat << 'EOF' > Dockerfile FROM ubuntu:18.04 # Non administrative username ENV USERNAME=example # Add non administrative user RUN useradd -m ${USERNAME} # Add example group RUN groupadd -g 10000 example-users # Change user id and group id RUN usermod -u 10000 -g 10000 ${USERNAME} # Change user USER ${USERNAME} # Boot initial process CMD bash EOF
イメージのビルドとコンテナの起動のために、次のように Docker Compose 用の設定ファイルも用意しておく。
$ cat << 'EOF' > docker-compose.yml version: "3" services: example: build: context: . image: example/permission volumes: - ./:/mnt/working EOF
まずはイメージをビルドする。
$ sudo docker-compose build
続いてコンテナを起動する。
$ sudo docker-compose run --rm example
起動したコンテナでは、次の通り 10000:10000
の UID と GID を持ったユーザでログインしている。
$ whoami example $ id uid=10000(example) gid=10000(example-users) groups=10000(example-users)
マウントしたディレクトリに移動してファイルを作ってみよう。 すると、ディレクトリに権限がないため書き込むことができない。
$ cd /mnt/working/ $ echo "Hello, World" > greet-docker.txt bash: greet-docker.txt: Permission denied
毎回 sudo するという手もなくはないけど、めんどくさい。
コンテナで /etc/passwd
と /etc/group
をマウントしてみる
先ほどの問題を解決すべく、コンテナから /etc/passwd
と /etc/group
をマウントしてみる。
コンテナ側からは書き換えできないように、念のため ro (Read Only) フラグをつけておく。
/home
についてはお好みで。
$ cat << 'EOF' > docker-compose.yml version: "3" services: example: image: ubuntu:18.04 volumes: - /etc/passwd:/etc/passwd:ro - /etc/group:/etc/group:ro - /home:/home - ./:/mnt/working EOF
起動時に -u
オプションで実行時のユーザの UID と GID を指定できる。
次のようにすれば現在のユーザをそのまま引き継げる。
$ sudo docker-compose run \ -u "$(id -u $USER):$(id -g $USER)" \ --rm \ example
コンテナ内でも、ホスト側と同じユーザとして見えることがわかる。
$ whoami vagrant $ id uid=1000(vagrant) gid=1000(vagrant) groups=1000(vagrant)
これは、ユーザとグループに関する情報がコンテナとホストで共有されているため。
$ grep vagrant /etc/passwd vagrant:x:1000:1000:,,,:/home/vagrant:/bin/bash
先ほどと同じようにマウントされているディレクトリに移動してファイルを作ってみよう。 コンテナとホストで UID と GID が一致しているため、ちゃんと書き込むことができている。
$ cd /mnt/working/ $ echo "Hello, World" > greet-docker.txt $ ls -lF total 20 -rw-rw-r-- 1 vagrant vagrant 324 Sep 19 09:18 Dockerfile -rw-rw-r-- 1 vagrant vagrant 183 Sep 19 11:08 docker-compose.yml -rw-r--r-- 1 root root 13 Sep 19 09:14 greet-docker-root.txt -rw-rw-r-- 1 vagrant vagrant 13 Sep 19 11:11 greet-docker.txt -rw-rw-r-- 1 vagrant vagrant 13 Sep 19 09:10 greet.txt
今回のやり方では、コンテナのプラットフォーム間でのポータビリティは低下するというデメリットがある。
もし、プラットフォーム間のポータビリティも落としたくない場合は、ENTRYPOINT
のスクリプトでユーザを編集する必要があるだろう。
とはいえ、そこを割り切って手っ取り早く解決する方法の一つとしては使い所を選べばありだと感じた。
参考
- 作者:もみじあめ
- 発売日: 2020/02/29
- メディア: Kindle版