ottijp blog

Dockerコンテナの既存ディレクトリにマウントしたら,オーナやパーミションがどうなるか

2022-01-22linuxdocker

環境

  • ubuntu 20.04
  • Docker Engine - Community 20.10

調べたこと

Dockerの既存ディレクトリにバインドマウントやボリュームマウントを使った際に, オーナやパーミションがどうなるのか調べました.

結果

  • バインドマウントの場合,ホストのオーナとパーミションのままになります.
  • ボリュームマウントの場合,ボリュームが空かどうかに依って挙動が変わります.

    • マウントするボリュームが空である場合, コンテナのオーナ,パーミションに変更されます.(コンテナの既存ディレクトリが,中にあるファイル含めてまるごとボリュームにコピーされます.)
    • マウントするボリュームが空でない(中にファイルが存在する)場合, ホストのオーナとパーミションのままになります.

コンテナのマウント先ディレクトリを空にしたいかどうか, コンテナのマウント先ディレクトリの状態を元にボリュームを作りたいかどうか などによって使い分けるのがよさそうです.

ちなみに,マウント先のディレクトリが存在しない場合,当然ながら,バインドマウントでもボリュームマウントでも,ホストのオーナとパーミションのままになります.

調査ログ

準備

マウント先のディレクトリを持つイメージを作っておきます.

FROM busybox

RUN adduser -D -u 42 cuser
RUN mkdir -p /work_existing
RUN chown cuser:cuser /work_existing
RUN chmod go+w /work_existing

RUN ls -ld /work_existing
RUN ls -ldn /work_existing
$ sudo docker build -t dir-inspection .
Sending build context to Docker daemon  18.94kB
Step 1/7 : FROM busybox
 ---> beae173ccac6
Step 2/7 : RUN adduser -D -u 42 cuser
 ---> Running in 06ac9d263762
Removing intermediate container 06ac9d263762
 ---> 39dc849cbbea
Step 3/7 : RUN mkdir -p /work_existing
 ---> Running in c6663ee5467f
Removing intermediate container c6663ee5467f
 ---> f7139cac2de2
Step 4/7 : RUN chown cuser:cuser /work_existing
 ---> Running in fea9cc3c5c60
Removing intermediate container fea9cc3c5c60
 ---> 6630bd739fcb
Step 5/7 : RUN chmod go+w /work_existing
 ---> Running in 15afb53ec001
Removing intermediate container 15afb53ec001
 ---> 69765c0256c3
Step 6/7 : RUN ls -ld /work_existing
 ---> Running in 911003bbe88f
drwxrwxrwx    1 cuser    cuser         4096 Jan 22 10:34 /work_existing
Removing intermediate container 911003bbe88f
 ---> 4b710f9e9714
Step 7/7 : RUN ls -ldn /work_existing
 ---> Running in 251032f6b2d1
drwxrwxrwx    1 42       42            4096 Jan 22 10:34 /work_existing
Removing intermediate container 251032f6b2d1
 ---> 40919782236a
Successfully built 40919782236a
Successfully tagged dir-inspection:latest

バインドマウント

バインド用のホストのディレクトリを作ります.

$ mkdir hoge
$ ls -ld hoge
drwxrwxr-x 2 vagrant vagrant 4096 Jan 22 10:36 hoge
$ ls -ldn hoge
drwxrwxr-x 2 1000 1000 4096 Jan 22 10:36 hoge

コンテナに存在しないパスにマウントしてみます.

$ sudo docker run -it --rm -v $PWD/hoge:/work dir-inspection
/ # ls -ld /work
drwxrwxr-x    2 1000     1000          4096 Jan 22 10:36 /work
/ # ls -ldn /work
drwxrwxr-x    2 1000     1000          4096 Jan 22 10:36 /work

当然ながらホストと同じオーナとパーミションになりました.

つぎに,コンテナに存在するパス(ホストとオーナ,パーミションが異なる)にマウントしてみます.

$ sudo docker run -it --rm -v $PWD/hoge:/work_existing dir-inspection
/ # ls -ld /work_existing/
drwxrwxr-x    2 1000     1000          4096 Jan 22 10:36 /work_existing/
/ # ls -ldn /work_existing/
drwxrwxr-x    2 1000     1000          4096 Jan 22 10:36 /work_existing/

これも,ホストと同じオーナとパーミションになりました.

ボリュームマウント(手動作成したボリューム)

ボリュームを手動で作ります.

$ sudo docker volume create vol_hoge
vol_hoge
$ sudo docker volume inspect vol_hoge
[
    {
        "CreatedAt": "2022-01-22T10:42:37Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/vol_hoge/_data",
        "Name": "vol_hoge",
        "Options": {},
        "Scope": "local"
    }
]
$ sudo ls -ld /var/lib/docker/volumes/vol_hoge/_data
drwxr-xr-x 2 root root 4096 Jan 22 10:42 /var/lib/docker/volumes/vol_hoge/_data
$ sudo ls -ldn /var/lib/docker/volumes/vol_hoge/_data
drwxr-xr-x 2 0 0 4096 Jan 22 10:42 /var/lib/docker/volumes/vol_hoge/_data

オーナはrootで作成されました.

これを,コンテナに存在しないパスにマウントしてみます.

$ sudo docker run -it --rm -v vol_hoge:/work dir-inspection
/ # ls -ld /work
drwxr-xr-x    2 root     root          4096 Jan 22 10:42 /work
/ # ls -ldn /work
drwxr-xr-x    2 0        0             4096 Jan 22 10:42 /work

当然ながらホストと同じオーナとパーミションになりました.

つぎに,コンテナに存在するパス(ホストとオーナ,パーミションが異なる)にマウントしてみます.

$ sudo docker run -it --rm -v vol_hoge:/work_existing dir-inspection
/ # ls -ld /work_existing/
drwxrwxrwx    2 cuser    cuser         4096 Jan 22 10:34 /work_existing/
/ # ls -ldn /work_existing/
drwxrwxrwx    2 42       42            4096 Jan 22 10:34 /work_existing/
/ # exit

$ sudo ls -ld /var/lib/docker/volumes/vol_hoge/_data
drwxrwxrwx 2 42 shadow 4096 Jan 22 10:34 /var/lib/docker/volumes/vol_hoge/_data
$ sudo ls -ldn /var/lib/docker/volumes/vol_hoge/_data
drwxrwxrwx 2 42 42 4096 Jan 22 10:34 /var/lib/docker/volumes/vol_hoge/_data

コンテナに存在するパスのオーナとパーミションに変更されました. ホスト上でもオーナとパーミションが変わったことが確認できます.

これはDockerのドキュメントにあるように,コンテナの内容がコピーされたということだと思います.

cf. Docker におけるデータ管理 | Docker ドキュメント

コンテナー内のディレクトリに 空のボリューム をマウントしようとしていて、そのディレクトリ内にファイルやディレクトリが存在する場合、そのファイルやディレクトリはボリューム内にコピーされます。 コンテナー起動時に指定したボリュームがまだ存在していなかった場合は、空のボリュームが生成されます。 コンテナーの求めに応じて事前にデータを提供しておく方法として用いられます。

ドキュメントには「そのディレクトリ内にファイルやディレクトリが存在する場合」とありますが,ファイルやディレクトリが存在しなくても,マウント先のディレクトリ自体のオーナ,パーミションはコピーされるようです.

ボリュームマウント(自動作成されるボリューム)

コンテナに存在しないパスにマウントしてみます.

$ sudo docker run -it --rm -v vol_hoge_auto:/work dir-inspection
/ # ls -ld /work
drwxr-xr-x    2 root     root          4096 Jan 22 10:50 /work
/ # ls -ldn /work
drwxr-xr-x    2 0        0             4096 Jan 22 10:50 /work
/ # exit

$ sudo docker volume inspect vol_hoge_auto
[
    {
        "CreatedAt": "2022-01-22T10:50:57Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/vol_hoge_auto/_data",
        "Name": "vol_hoge_auto",
        "Options": null,
        "Scope": "local"
    }
]
$ sudo ls -ld /var/lib/docker/volumes/vol_hoge_auto/_data
drwxr-xr-x 2 root root 4096 Jan 22 10:50 /var/lib/docker/volumes/vol_hoge_auto/_data
$ sudo ls -ldn /var/lib/docker/volumes/vol_hoge_auto/_data
drwxr-xr-x 2 0 0 4096 Jan 22 10:50 /var/lib/docker/volumes/vol_hoge_auto/_data

オーナはrootで作成され,ホストと同じオーナとパーミションになりました. (手動作成した場合と同様.)

つぎに,コンテナに存在するパス(ホストとオーナ,パーミションが異なる)にマウントしてみます.

$ sudo docker run -it --rm -v vol_hoge_auto:/work_existing dir-inspection
/ # ls -ld /work_existing/
drwxrwxrwx    2 cuser    cuser         4096 Jan 22 10:34 /work_existing/
/ # ls -ldn /work_existing/
drwxrwxrwx    2 42       42            4096 Jan 22 10:34 /work_existing/
/ # exit

$ sudo ls -ld /var/lib/docker/volumes/vol_hoge_auto/_datals
ls: cannot access '/var/lib/docker/volumes/vol_hoge_auto/_datals': No such file or directory
$ sudo ls -ld /var/lib/docker/volumes/vol_hoge_auto/_data
drwxrwxrwx 2 42 shadow 4096 Jan 22 10:34 /var/lib/docker/volumes/vol_hoge_auto/_data
$ sudo ls -ldn /var/lib/docker/volumes/vol_hoge_auto/_data
drwxrwxrwx 2 42 42 4096 Jan 22 10:34 /var/lib/docker/volumes/vol_hoge_auto/_data

これも,手動作成した場合と同様に,コンテナに存在するパスのオーナとパーミションに変更されました.

ボリュームが空でない場合

手動作成したボリュームにデータを入れた上で, コンテナに存在するパス(ホストとオーナ,パーミションが異なる)にマウントしてみました.

$ sudo docker volume create vol_hoge_with_file
vol_hoge_with_file

$ sudo docker run -it --rm -v vol_hoge_with_file:/work busybox
/ # touch /work/piyo
/ # exit

$ sudo docker run -it --rm -v vol_hoge_with_file:/work_existing dir-inspection
/ # ls -ld /work_existing/
drwxr-xr-x    2 root     root          4096 Jan 22 11:07 /work_existing/
/ # ls -ldn /work_existing/
drwxr-xr-x    2 0        0             4096 Jan 22 11:07 /work_existing/
/ # exit

空のボリュームの場合と異なり,ホストのオーナとパーミションは変更されず,そのままになりました.


ottijp
Satoshi SAKAO (@ottijp)

都内でアプリケーションエンジニアをしています

...