マウントしたボリュームのユーザ,グループの違いを解決するdocker-volume-bindfs

Dockerでローカルファイルをボリュームとしてマウントした場合、ユーザとグループの食い違いに悩むことがあります。
[docker-volume-bindfs](https://github.com/lebokus/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にあるとおり](https://github.com/lebokus/docker-volume-bindfs/blob/master/README.md) セキュリティー的な問題もあるため、開発環境での利用のみとし、Production環境では利用を控えた方がよさそうです。