DockerfileでVOLUME
を使ったりdocker run
の際に-v
オプションを利用することで、ホストのフォルダをコンテナにマウントできます。それにより、コンテナにおいてホストに存在するファイルを参照したり、逆にコンテナ内で作成したファイルをホストで操作できるようになります。
ただし、後者の場合はファイルのowner権限を考慮しておかないと、Permission deniedエラーを食らうこともあるので注意が必要です。
Busyboxコンテナ内で作成したファイルを、ホスト側で削除してみます。
sampleusr@foohost:~/foo$ id
uid=1000(sampleusr) gid=9999(testgr) groups=9999(testgr),999(docker)
sampleusr@foohost:~/foo$ mkdir hoge && touch hoge/hoge.txt
sampleusr@foohost:~/foo$ ls -al hoge
total 8
drwxr-xr-x 2 sampleusr testgr 4096 4月 20 16:41 .
drwxr-xr-x 4 sampleusr testgr 4096 4月 20 16:41 ..
-rw-r--r-- 1 sampleusr testgr 0 4月 20 16:41 hoge.txt
sampleusr@foohost:~/foo$ docker run -it -v $(pwd)/hoge:/hoge busybox
/ # ls -al /hoge
total 8
drwxr-xr-x 2 1000 9999 4096 Apr 20 07:41 .
drwxr-xr-x 1 root root 4096 Apr 20 07:42 ..
-rw-r--r-- 1 1000 9999 0 Apr 20 07:41 hoge.txt
/ # touch /hoge/foo.txt
/ # ls -al /hoge
total 8
drwxr-xr-x 2 1000 9999 4096 Apr 20 07:43 .
drwxr-xr-x 1 root root 4096 Apr 20 07:42 ..
-rw-r--r-- 1 root root 0 Apr 20 07:43 foo.txt
-rw-r--r-- 1 1000 9999 0 Apr 20 07:41 hoge.txt
/ # exit
sampleusr@foohost:~/foo$ ls -al hoge
total 8
drwxr-xr-x 2 sampleusr testgr 4096 4月 20 16:43 .
drwxr-xr-x 4 sampleusr testgr 4096 4月 20 16:41 ..
-rw-r--r-- 1 root root 0 4月 20 16:43 foo.txt
-rw-r--r-- 1 sampleusr testgr 0 4月 20 16:41 hoge.txt
sampleusr@foohost:~/foo$ rm hoge/foo.txt
rm: remove write-protected regular empty file 'hoge/foo.txt'? y
rm: cannot remove 'hoge/foo.txt': Permission denied
コンテナ内で作成したファイルfoo.txt
はownerがrootになっているため、そのファイルをホストで削除しようとしても(ホストでは一般ユーザーとしてログインしているので)Permission denidとメッセージが出力されます。
コンテナにおいてrootとしてログインして作業していた場合、その権限設定はそのままホストでも参照されるので「(一般ユーザーのお前じゃ)ファイルにアクセスする権限ないぞ」と怒られるわけですね。
sampleusr@foohost:~/foo$ mkdir hoge
sampleusr@foohost:~/foo$ docker run -it -v $(pwd)/hoge:/hoge busybox
/ # mkdir -p /hoge/fuga/piyo
/ # exit
sampleusr@foohost:~/foo$ ls -al hoge
total 12
drwxr-xr-x 3 sampleusr testgr 4096 4月 21 13:19 .
drwxr-xr-x 4 sampleusr testgr 4096 4月 21 13:18 ..
drwxr-xr-x 3 root root 4096 4月 21 13:19 fuga
sampleusr@foohost:~/foo$ touch hoge/fuga/piyo/foo.txt
touch: cannot touch 'hoge/fuga/piyo/foo.txt': Permission denied
他のケースとしては、コンテナ内で作成されたフォルダに対しファイルを作成しようした場合に、同様の権限エラーが起きます。このケースでもさっきと同様に、フォルダのownerがrootになっているため、ホスト側でログインしている一般ユーザーの権限では参照できないからです。もちろんフォルダの削除も不可。
この現象は、どうもLinuxのホストでLinuxのコンテナを利用するときに発生するようで、ホストがWindowsかmacOSの場合は発現しませんでした。はっきりとした理由は不明ですが、Dockerがうまいことハンドリングしてくれているのかもしれません。
根本的な原因は、コンテナで作業する際のユーザーがrootであることです。ホスト側の権限と同じであれば、このようなエラーは発生し得ません。となれば、コンテナ内の作業ユーザーをホスト側の権限と同じにしてやればいいわけです。
対処法はいくつか考えられますが、簡単なのはコンテナ内でuseradd
して一般ユーザーを作成し、作成した一般ユーザーで処理を実行するというもの。useradd
する際に、ホスト側のユーザーに関するUIDやGIDをそのまま渡してやれば一番簡単です。
docker run
などでコンテナ起動する場合は、-u
オプションで起動時のUIDやGIDをコンテナに引き継ぐ方法もあります。ただし、この方法は/etc/passwd
と/etc/group
をコンテナにボリュームマウントする必要があるので忘れないよう指定しましょう。
「Linux環境でLinuxのコンテナを使うときだけ発現する」ケースのエラーでしたので、場合によっては一度も遭遇したことのない人がもしかしたらいらっしゃるかもしれません。往々にして、特定環境でのみ発生するエラーケースは対処法を探すのが結構骨だったりします。この記事が一助になれば幸いです。