頑張らないために頑張る

ゆるく頑張ります

コンテナ内で作成したファイルをホストで操作するとPermission deniedが発生する

Posted at — Apr 29, 2021

概要

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のホストでLinuxのコンテナを利用するときに発生するようで、ホストがWindowsかmacOSの場合は発現しませんでした。はっきりとした理由は不明ですが、Dockerがうまいことハンドリングしてくれているのかもしれません。

どうすりゃいいのよ

根本的な原因は、コンテナで作業する際のユーザーがrootであることです。ホスト側の権限と同じであれば、このようなエラーは発生し得ません。となれば、コンテナ内の作業ユーザーをホスト側の権限と同じにしてやればいいわけです。

対処法はいくつか考えられますが、簡単なのはコンテナ内でuseraddして一般ユーザーを作成し、作成した一般ユーザーで処理を実行するというもの。useraddする際に、ホスト側のユーザーに関するUIDやGIDをそのまま渡してやれば一番簡単です。

docker runなどでコンテナ起動する場合は、-uオプションで起動時のUIDやGIDをコンテナに引き継ぐ方法もあります。ただし、この方法は/etc/passwd/etc/groupをコンテナにボリュームマウントする必要があるので忘れないよう指定しましょう。

まとめ

「Linux環境でLinuxのコンテナを使うときだけ発現する」ケースのエラーでしたので、場合によっては一度も遭遇したことのない人がもしかしたらいらっしゃるかもしれません。往々にして、特定環境でのみ発生するエラーケースは対処法を探すのが結構骨だったりします。この記事が一助になれば幸いです。

参照

  1. Use volumes
  2. dockerでvolumeをマウントしたときのファイルのowner問題
  3. Docker コンテナ内で Docker ホストと同じユーザを使う
comments powered by Disqus