Dockerでローカルファイルをボリュームとしてマウントした場合、ユーザとグループの食い違いに悩むことがあります。
docker-volume-bindfs を使うと、それらの悩みを解決することができます。
Ubuntuで確認
現在ログイン中のUID, GIDを確認する
$ id -u
1000
$ id -g
1000
空ファイルを作る
$ touch hello
$ ls -al
total 8
drwxrwxr-x 2 user user 4096 1月 16 12:27 .
drwxrwxr-x 7 user user 4096 1月 16 12:27 ..
-rw-rw-r-- 1 user user 0 1月 16 12:27 hello
まずは普通にVolumeでマウントしてみる
$ docker run --rm -it -v $(pwd):/vol busybox ls -al /vol
total 8
drwxrwxr-x 2 1000 1000 4096 Jan 16 03:27 .
drwxr-xr-x 1 root root 4096 Jan 16 03:49 ..
-rw-rw-r-- 1 1000 1000 0 Jan 16 03:27 hello
ユーザとグループが 1000,1000になっていることが確認できます
bindfs プラグインの導入
$ docker plugin install lebokus/bindfs
Plugin "lebokus/bindfs" is requesting the following privileges:
- mount: [/var/lib/docker/plugins/]
- mount: [/]
- device: [/dev/fuse]
- capabilities: [CAP_SYS_ADMIN]
Do you grant the above permissions? [y/N] y
現在のユーザでカレントディレクトリをrootにマッピングするNamed Volumeを作る
$ docker volume create \
-d lebokus/bindfs \
-o sourcePath=$(pwd) \
-o map=$(id -u)/0:@$(id -g)/@0 \
bindfs_volume
マウントして確認してみる
$ docker run --rm -it -v bindfs_volume:/vol busybox ls -al /vol
total 8
drwxrwxr-x 2 root root 4096 Jan 16 03:27 .
drwxr-xr-x 1 root root 4096 Jan 16 03:37 ..
-rw-rw-r-- 1 root root 0 Jan 16 03:27 hello
ユーザ・グループともにrootになりました。
ボリュームを削除します
$ docker volume rm bindfs_volume
コンテナ内にappuserを作成し、そのユーザにローカルのユーザを割り当てる
実験用イメージ作成を作成します。UID,GID 10000 で appuserを作成しています。
$ cat Dockerfile
FROM alpine:latest
RUN set -xe && adduser -u 10000 -D appuser
$ docker build -t bindfs-test .
ローカルユーザをUID:10000, GID:10000 にマッピングします
$ docker volume create \
-d lebokus/bindfs \
-o sourcePath=$(pwd) \
-o map=$(id -u)/10000:@$(id -g)/@10000 \
bindfs_volume
appuserでログインします
$ docker run --rm -it -v bindfs_volume:/home/appuser/data bindfs-test login -f appuser
$ ls -al data
total 12
drwxrwxr-x 2 appuser appuser 4096 Jan 16 04:05 .
drwxr-sr-x 1 appuser appuser 4096 Jan 16 04:10 ..
-rw-rw-r-- 1 appuser appuser 72 Jan 16 04:05 Dockerfile
-rw-rw-r-- 1 appuser appuser 0 Jan 16 03:27 hello
ローカルユーザをマウントしたユーザ・グループが appuserにマッピングされています。
ファイルを作成してみます。
$ touch data/hoge
ログアウトしてコンテナを終了します。
$ exit
ローカルにあるファイルを確認してみます。
$ ls -al
total 12
drwxrwxr-x 2 user user 4096 1月 16 13:11 .
drwxrwxr-x 7 user user 4096 1月 16 12:27 ..
-rw-rw-r-- 1 user user 72 1月 16 13:05 Dockerfile
-rw-rw-r-- 1 user user 0 1月 16 12:27 hello
-rw-r--r-- 1 user user 0 1月 16 13:11 hoge
きちんとローカルのユーザ・グループで hoge が作成されています。
Docker for Macで確認
$ id -u
501
$ id -g
20
$ touch hello
$ ls -al
total 0
drwxr-xr-x 3 user staff 96 1 16 12:54 .
drwx------+ 25 user staff 800 1 16 12:54 ..
-rw-r--r-- 1 user staff 0 1 16 12:53 hello
$ docker run --rm -it -v $(pwd):/vol busybox ls -al /vol
total 4
drwxr-xr-x 3 root root 96 Jan 16 03:54 .
drwxr-xr-x 1 root root 4096 Jan 16 03:55 ..
-rw-r--r-- 1 root root 0 Jan 16 03:53 hello
Docker for Macの場合、標準でroot:root への割当が行われているようです。 appuserへの割当を試してみます。
実験用イメージ作成
$ cat Dockerfile
FROM alpine:latest
RUN set -xe && adduser -u 10000 -D appuser
$ docker build -t bindfs-test .
プラグイン導入
$ docker plugin install lebokus/bindfs
Plugin "lebokus/bindfs" is requesting the following privileges:
- mount: [/var/lib/docker/plugins/]
- mount: [/]
- device: [/dev/fuse]
- capabilities: [CAP_SYS_ADMIN]
Do you grant the above permissions? [y/N] y
root(UID:0, GID:0)をUID:10000, GID:10000 にマッピングしたNamed Volumeの作成
$ docker volume create \
-d lebokus/bindfs \
-o sourcePath=$(pwd) \
-o map=0/10000:@0/@10000 \
bindfs_volume
appuserでログインし、ファイルを作成してみる。
$ docker run --rm -it -v bindfs_volume:/home/appuser/data bindfs-test login -f appuser
$ ls -al data
total 8
drwxr-xr-x 4 appuser appuser 128 Jan 16 04:00 .
drwxr-sr-x 1 appuser appuser 4096 Jan 16 04:21 ..
-rw-r--r-- 1 appuser appuser 62 Jan 16 04:16 Dockerfile
-rw-r--r-- 1 appuser appuser 0 Jan 16 03:53 hello
$ touch data/hoge
ログアウトしてコンテナを終了し、作成したファイルを確認してみる。
$ exit
$ ls -al
total 8
drwxr-xr-x 5 user staff 160 1 16 13:21 .
drwx------+ 25 user staff 800 1 16 12:54 ..
-rw-r--r-- 1 user staff 62 1 16 13:16 Dockerfile
-rw-r--r-- 1 user staff 0 1 16 12:53 hello
-rw-r--r--@ 1 user staff 0 1 16 13:21 hoge
きちんとローカルのユーザ・グループで hoge が作成されています。
Named Volumeの削除とプラグインの無効化と削除
$ docker volume rm bindfs_volume
$ docker plugin disable lebokus/bindfs
$ docker plugin rm lebokus/bindfs
まとめ
docker-volume-bindfs は 透過的にユーザ・グループのマッピングをおこなってくれるので、ローカル側のファイルの参照が必要な開発用途などに重宝しそうです。ただ、READMEにあるとおり セキュリティー的な問題もあるため、開発環境での利用のみとし、Production環境では利用を控えた方がよさそうです。