Help us understand the problem. What is going on with this article?

dockerで共有ディレクトリを利用したが、「Permission denied」が出てアクセスできない。

More than 3 years have passed since last update.

事象

dockerにてホストのディレクトリをコンテナと共有をしようと思ったが、「Permission denied」が出てアクセスできなかった。

使用した環境

サーバ:Microsoft Azure
OS:Red Hat Enterprise Linux 7.2
docker:version 1.10.3

事象が発生したコマンド

[user@host ~]$ mkdir testdir
[user@host ~]$ touch testdir/aaa.txt
[user@host ~]$ sudo docker run -i -t -v $HOME/testdir:/testdir ubuntu /bin/bash

#以下、コンテナ内のコマンド
root@a3eb3ad27df4:/# ls /testdir/
ls: cannot open directory '/testdir/': Permission denied

発生原因の仮説

No. 原因の仮説 結果
ホスト側ディレクトリのパーミッション設定が原因
dockerプロセスのユーザが原因
その他、何かのセキュリティ要素が原因 原因

仮説検証

仮説検証1:ホスト側ディレクトリのパーミッション

ホスト側ディレクトリのパーミッション設定の確認を行ってみる。

#ホスト側
[user@host ~]$ ls -l
total 0
drwxrwxr-x. 2 user user 20 Mar  6 08:03 testdir

次にコンテナ側ディレクトリのパーミッション設定の確認を行ってみる。

#ホスト側
[user@host ~]$ sudo docker run -i -t -v $HOME/testdir:/testdir ubuntu ls -l /
total 16
#略
drwxrwxr-x.   2 1000 1000   20 Mar  6 08:03 testdir
drwxrwxrwt.   2 root root    6 Jan 19 16:33 tmp
#略

ユーザとグループがおかしくなっていることが確認できました。
ホスト側のディレクトリとコンテナ側のユーザを同じ(root)にしてみたいと思います。

#ホスト側
[user@host ~]$ rm -df testdir
[user@host ~]$ ls -l
total 0
drwxr-xr-x. 2 root      root       6 Mar  7 04:29 testdir
[user@host ~]$ sudo docker run -i -t -v $HOME/testdir:/testdir ubuntu ls -l /
total 16
#略
drwxr-xr-x.   2 root root    6 Mar  7 04:29 testdir
drwxrwxrwt.   2 root root    6 Jan 19 16:33 tmp
#略

ホストとコンテナのディレクトリ所有ユーザが同じになりました。これでいけるはず!
再度コンテナでlsを実行します。

#ホスト側
[user@host ~]$ sudo docker run -i -t -v $HOME/testdir:/testdir ubuntu /bin/bash
#コンテナ側
root@826f647d35fb:/# ls -l testdir/
ls: cannot open directory 'testdir/': Permission denied

だめでした。パーミッションが原因ではないらしいです。

仮説検証2:dockerプロセスのユーザが原因

dockerサービスが何か得体のしれないユーザで動いているかもしれないので確認します。

[user@host ~]$ cat /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=http://docs.docker.com
After=network.target
Wants=docker-storage-setup.service
Requires=rhel-push-plugin.socket

[Service]
Type=notify
NotifyAccess=all
EnvironmentFile=-/etc/sysconfig/docker
EnvironmentFile=-/etc/sysconfig/docker-storage
EnvironmentFile=-/etc/sysconfig/docker-network
Environment=GOTRACEBACK=crash
ExecStart=/usr/bin/docker-current daemon \
          --authorization-plugin=rhel-push-plugin \
          --exec-opt native.cgroupdriver=systemd \
          $OPTIONS \
          $DOCKER_STORAGE_OPTIONS \
          $DOCKER_NETWORK_OPTIONS \
          $ADD_REGISTRY \
          $BLOCK_REGISTRY \
          $INSECURE_REGISTRY
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
TimeoutStartSec=0
MountFlags=slave
Restart=on-abnormal

[Install]
WantedBy=multi-user.target

特にそれらしき設定も見つからず、dockerサービスの実行ユーザが原因ではないらしいです。

仮説検証3:何かのセキュリティ要因

パーミッション周りの設定だと思っていたのであっさり解決するかと思っていましたが、ダメでした。
職場のパイセンに相談してみたところ「SELinuxじゃね?」とのこと。そういや無効か設定した記憶がありません。

まずは一時的に無効化して試してみます。

#ホスト側
[user@host ~]$ getenforce
Enforcing
[user@host ~]$ sudo setenforce 0
[user@host ~]$ sudo docker run -i -t -v $HOME/testdir:/testdir ubuntu /bin/bash
#コンテナ側
root@fccb3b63af38:/# ls testdir/
root@fccb3b63af38:/# cd testdir/
root@fccb3b63af38:/testdir# echo 'testtext' > test.txt
root@fccb3b63af38:/testdir# exit
exit
#ホスト側
[user@host ~]$ cat testdir/test.txt
testtext

おおお!無事に見れました。SELinuxが原因だったようです。
さすがです。パイセン!

原因の掘り下げ

しかし、SELinuxを無効化しよう!が解決方法だと何か違う気もするのでさらに掘り下げます。
まずはラベルの確認をします。

#ホスト側
[user@host ~]$ sudo setenforce 1
[user@host ~]$ getenforce
Enforcing
[user@host ~]$ ls -Z
drwxr-xr-x. root      root      unconfined_u:object_r:user_home_t:s0 testdir
[user@host ~]$ sudo docker run -i -t -v $HOME/testdir:/testdir ubuntu /bin/bash
#コンテナ側
root@1a46f7be5d12:/# ls -Zl
total 16
drwxr-xr-x.   2 root root unconfined_u:object_r:user_home_t:s0                  21 Mar  7 05:01 testdir
drwxrwxrwt.   2 root root system_u:object_r:svirt_sandbox_file_t:s0:c120,c472    6 Jan 19 16:33 tmp
root@1a46f7be5d12:/# id
uid=0(root) gid=0(root) groups=0(root)

コンテナ側のディレクトリのラベルと共有したディレクトリのラベルに差がありますね。この辺のラベルを合わせれば上手く動くような気がします。
tmp:system_u:object_r:svirt_sandbox_file_t:s0:c120,c472
testdir:unconfined_u:object_r:user_home_t:s0
ラベルを自力で変更しようかとも思いましたが、dockerに既にいい感じにしてくれる機能が用意されていました。
オプション-vの最後に:Zをつけるといい感じにラベルを設定してくれます。

#ホスト側
[user@host ~]$ ls -Z
drwxr-xr-x. root      root      unconfined_u:object_r:user_home_t:s0 testdir
[user@host ~]$ sudo docker run -i -t -v $HOME/testdir:/testdir:Z ubuntu /bin/bash
#コンテナ側
root@dedc05f3a4c4:/# ls testdir/
test.txt
root@dedc05f3a4c4:/# cat testdir/test.txt
testtext
root@dedc05f3a4c4:/# exit
exit
#ホスト側
[user@host ~]$ ls -Z
drwxr-xr-x. root      root      system_u:object_r:svirt_sandbox_file_t:s0:c24,c110 testdir

testdirのラベルが変わっています。

ラベル
Before unconfined_u:object_r:user_home_t:s0
After system_u:object_r:svirt_sandbox_file_t:s0:c24,c110

:Zは匠です。

原因

SELinuxと適切にラベルが付与されていないのが原因

解決方法

-vオプションの最後に:zをつける。

[user@host ~]$ sudo docker run -i -t -v $HOME/testdir:/testdir:Z ubuntu /bin/bash
shuichiro
社内の研修を企画したり、新しいものを試したりしています。 悩んだことを残していこうと思います。 投稿する記事の内容は個人の意見であり、所属する企業の見解を代表するものではありません。
japan-systems
「2019年に50周年を迎えたIT企業です。最先端の技術により全国の企業、官公庁、自治体に多くの実績があります。」
https://www.japan-systems.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away