Dockerのホストディレクトリへのアクセス許可が拒否されました


282

つまり、Dockerでホストディレクトリをマウントしようとしていますが、アクセス権限に問題がないように見えても、コンテナー内からアクセスできません。

詳細:

私がやっている

sudo docker run -i -v /data1/Downloads:/Downloads ubuntu bash

その後

ls -al

それは私に与えます:

total 8892
drwxr-xr-x.  23 root root    4096 Jun 18 14:34 .
drwxr-xr-x.  23 root root    4096 Jun 18 14:34 ..
-rwxr-xr-x.   1 root root       0 Jun 18 14:34 .dockerenv
-rwx------.   1 root root 9014486 Jun 17 22:09 .dockerinit
drwxrwxr-x.  18 1000 1000   12288 Jun 16 11:40 Downloads
drwxr-xr-x.   2 root root    4096 Jan 29 18:10 bin
drwxr-xr-x.   2 root root    4096 Apr 19  2012 boot
drwxr-xr-x.   4 root root     340 Jun 18 14:34 dev
drwxr-xr-x.  56 root root    4096 Jun 18 14:34 etc
drwxr-xr-x.   2 root root    4096 Apr 19  2012 home

そのような行がもっとたくさんあります(これは関連する部分だと思います)。

私が行った場合

cd /Downloads
ls

結果は

ls: cannot open directory .: Permission denied

ホストはDocker 1.0.0とgo1.2.2を備えたFedora 20です。

何が問題になっていますか?

回答:


269

詳細については、ボリュームとSELinuxに関するこのProject Atomicブログ投稿を参照してください。

具体的には:

Dockerが最後にdocker-1.7に表示されるパッチをマージしたため、これは最近簡単になりました(RHEL、CentOS、およびFedoraのdocker-1.6でパッチを実行しています)。

このパッチは、ボリュームマウント(-v)のオプションとして「z」と「Z」のサポートを追加します。

例えば:

docker run -v /var/db:/var/db:z rhel7 /bin/sh

chcon -Rt svirt_sandbox_file_t /var/db マニュアルページに記載されている説明を自動的に行います。

さらに、Zを使用できます。

docker run -v /var/db:/var/db:Z rhel7 /bin/sh

これにより、コンテナー内のコンテンツに、コンテナーの実行に使用される正確なMCSラベルが付けられます。基本的に、コンテナーごとchcon -Rt svirt_sandbox_file_t -l s0:c1,c2 /var/dbs0:c1,c2異なる場所で実行されます。


18
これは魅力のように機能します。他の解決策は主に回避策です。
tuxdna 2016年

4
cf.
Docker

ああ、それは本当にうまくいきます。やっとこれを見つけました。どうもありがとう!これに関する公式のドキュメントはありますか?
Kirby

1
上流には、このセクションの最後の段落としてそれを持っている docs.docker.com/engine/reference/commandline/run/...
gregswift

1
両方のオプションを同時にコンマで区切って使用することにより、ボリュームを同時に読み取り専用としてマウントしながら、SELinuxで権限を修正できます-v $(pwd):/app:ro,Z。これは正解としてマークする必要があります。
ダニロッド

263

これはSELinuxの問題です。

一時的に発行できます

su -c "setenforce 0"

ホスト上でアクセスするか、実行してSELinuxルールを追加します

chcon -Rt svirt_sandbox_file_t /path/to/volume

3
/ path / to / volumeはホストのパスですか?もしそうなら、このソリューションがデータコンテナで機能するようには思えませんか?
Roy Truelove 2014年

6
su -c "setenforce 1"を実行することを忘れないでください...そうしないと、SELinuxがまだ非アクティブ化されているためにのみ機能します
vcarel

これは私の問題を解決しました。ありがとう、私は彼らがこれを修正することを望みます。
北斗星

19
ほとんどの場合、特権モードでコンテナを実行することはお勧めできないため、selinuxルールを追加するのが最善の方法です。
Zoro_77 2015

7
Zoro_77が言ったように、ルールを追加し、stopdisablingselinux.com ;)
GabLeRoux

71

警告:このソリューションにはセキュリティ上のリスクがあります。

特権付きでコンテナを実行してみてください:

sudo docker run --privileged=true -i -v /data1/Downloads:/Downloads ubuntu bash

別のオプション(私は試していません)は、特権コンテナーを作成し、その中に非特権コンテナーを作成することです。


1
@JBernardo 2つのオプションのどちらが問題を解決しましたか?
user100464 2014年

@ user100464--privileged=true
JBernardo

1
私の場合は助けないでください。カーネル3.16がバックポートされているが、SELinux構成がアクティブ化されていないDebian Whezzy。:(
aholbreich 14

docker-composerを使用する場合、「privileged:true」を追加します
Lionel Morrison

35
こんなことしないで。--privilegedはセキュリティリスクです
Navin、2016年

38

通常、ホストボリュームマウントの権限の問題は、コンテナ内のuid / gidが、ホスト上のファイルのuid / gid権限に従ってファイルにアクセスできないために発生します。ただし、この特定のケースは異なります。

許可文字列の最後にあるドットは、drwxr-xr-x.SELinuxが構成されていることを示します。SELinuxでホストマウントを使用する場合、ボリューム定義の最後に追加のオプションを渡す必要があります。

  • このzオプションは、バインドマウントコンテンツが複数のコンテナー間で共有されることを示します。
  • Zオプションは、バインドマウントコンテンツがプライベートであり、共有されていないことを示します。

ボリュームマウントコマンドは次のようになります。

sudo docker run -i -v /data1/Downloads:/Downloads:z ubuntu bash

SELinuxでのホストマウントの詳細については、以下を参照してください。 https。


別のユーザーとして実行されているコンテナーでこの問題が発生する場合は、コンテナー内のユーザーのuid / gidがホスト上のファイルへのアクセス許可を持っていることを確認する必要があります。本番サーバーでは、多くの場合、イメージビルドプロセスのuid / gidを制御して、ファイルにアクセスできるホストのuid / gidと一致させます(さらに、本番環境ではホストマウントを使用しないでください)。

名前付きボリュームは、ファイルの所有権や権限を含め、イメージディレクトリからボリュームディレクトリを初期化するため、ホストマウントよりも好まれます。これは、ボリュームが空で、名前付きボリュームでコンテナーが作成された場合に発生します。

MacOSユーザーは、Macホストとコンテナ間でuid / gidを自動的に処理するOSXFSを使用できるようになりました。それが役に立たない1つの場所は、/ var / lib / docker.sockのように、コンテナーにマウントされる組み込みVM内のファイルです。

ホストuid / gidが開発者ごとに変更される可能性がある開発環境では、ルートとして実行されているエントリポイントでコンテナーを起動し、コンテナー内のユーザーのuid / gidを修正して、ホストボリュームuid / gidに一致させます。次に、を使用gosuしてルートからコンテナーユーザーにドロップし、コンテナー内でアプリケーションを実行します。このための重要なスクリプトはfix-permshttps//github.com/sudo-bmitch/docker-baseにある私のベースイメージスクリプトにあります。

fix-permsスクリプトの重要な部分は次のとおりです。

# update the uid
if [ -n "$opt_u" ]; then
  OLD_UID=$(getent passwd "${opt_u}" | cut -f3 -d:)
  NEW_UID=$(stat -c "%u" "$1")
  if [ "$OLD_UID" != "$NEW_UID" ]; then
    echo "Changing UID of $opt_u from $OLD_UID to $NEW_UID"
    usermod -u "$NEW_UID" -o "$opt_u"
    if [ -n "$opt_r" ]; then
      find / -xdev -user "$OLD_UID" -exec chown -h "$opt_u" {} \;
    fi
  fi
fi

これは、コンテナー内のユーザーのuidとファイルのuidを取得し、それらが一致しない場合はusermod、uidを調整するための呼び出しを行います。最後に、uidを変更していないファイルを修正するために再帰的検索を行います。-u $(id -u):$(id -g)上記のエントリポイントコードでは、各開発者がスクリプトを実行してコンテナを起動する必要がなく、ユーザーが所有するボリューム外のファイルのアクセス許可が修正されるため、フラグを付けてコンテナを実行するよりもこの方法が好きです。


バインドマウントを実行する名前付きボリュームを使用して、Dockerにイメージからホストディレクトリを初期化させることもできます。このディレクトリは事前に存在している必要があり、相対パスにすることができる構成ファイル内のホストボリュームとは異なり、ホストディレクトリへの絶対パスを指定する必要があります。dockerがディレクトリを初期化するには、ディレクトリも空である必要があります。名前付きボリュームをバインドマウントに定義するための3つの異なるオプションは、次のようになります。

  # create the volume in advance
  $ docker volume create --driver local \
      --opt type=none \
      --opt device=/home/user/test \
      --opt o=bind \
      test_vol

  # create on the fly with --mount
  $ docker run -it --rm \
    --mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=none,volume-opt=o=bind,volume-opt=device=/home/user/test \
    foo

  # inside a docker-compose file
  ...
  volumes:
    bind-test:
      driver: local
      driver_opts:
        type: none
        o: bind
        device: /home/user/test
  ...

最後に、ユーザー名前空間を使用しようとすると、コンテナーのuid / gidがシフトされるため、ホストボリュームに権限の問題があることがわかります。そのシナリオでは、ホストボリュームを避け、名前付きボリュームのみを使用するのがおそらく最も簡単です。


32

access.redhat.com:Sharing_Data_Across_Containersから:

ホストボリュームの設定は、ホストに依存し、他のマシンでは機能しない可能性があるため、移植できません。このため、コンテナにホストディレクトリをマウントするための同等のDockerfileはありません。また、ホストシステムはコンテナのSELinuxポリシーを認識していないことに注意してください。したがって、SELinuxポリシーが適用されている場合、マウントされたホストディレクトリは、rw設定に関係なく、コンテナに書き込みできません。現在、適切なSELinuxポリシータイプをホストディレクトリに割り当てることで、これを回避できます。 ":

chcon -Rt svirt_sandbox_file_t host_dir

ここで、host_dirは、コンテナーにマウントされているホストシステム上のディレクトリへのパスです。

単なる回避策のようですが、試してみましたがうまくいきました。


14

私はそれを確認しました chcon -Rt svirt_sandbox_file_t /path/to/volumeが機能するしました、そしてあなたは特権コンテナとして実行する必要はありません。

これはオンです:

  • Dockerバージョン0.11.1-dev、ビルド02d20af / 0.11.1
  • CentLinux 7をホストおよびコンテナとして使用し、SELinuxを有効にします。

2
Docker内でのラベル付けの公式サポートについては、github.com / docker / docker / pull / 5910を参照してください。
cpuguy83 2014年

13

お試しくださいdocker volume create

mkdir -p /data1/Downloads
docker volume create --driver local --name hello --opt type=none --opt device=/data1/Downloads --opt o=uid=root,gid=root --opt o=bind
docker run -i -v hello:/Downloads ubuntu bash

ドキュメントhttps://docs.docker.com/engine/reference/commandline/volume_create/をご覧ください


3
SOでこの問題について多くの回答を試しましたが、実際にはこれが役に立ちました。ありがとう!
ポール

それは許可のエラーを解決しました。しかし、私が物理的な場所をマウントしようとしている場合、それはvoulmeをマウントしますか???? @ cupen
kunal verma

1
@kunalvermaはい。気に入らない場合は、こちらが簡単な答えです。 stackoverflow.com/a/31334443/4909388
クーペン

4

私も同様の問題を抱えていました。ホストのUIDとコンテナーのユーザーのUIDの不一致が原因でした。修正は、ユーザーのUIDを引数としてdocker buildに渡し、同じUIDでコンテナーのユーザーを作成することでした。

DockerFileで:

ARG UID=1000
ENV USER="ubuntu"
RUN useradd -u $UID -ms /bin/bash $USER

ビルドステップ:

docker build <path/to/Dockerfile> -t <tag/name> --build-arg UID=$UID

その後、OPに従ってコンテナーとコマンドを実行すると、期待した結果が得られました。


1
実行時までUIDがわからない場合はどうなりますか?(私は同僚のためにイメージを作成しています。ファイルシステムに書き戻すいくつかのツールをパッケージ化するためですが、UIDが異なります)。私はそれをルートにして実行時にadduserだけを維持できると思いますか?
歌手

残念ながら、その答えはわかりません。他の誰かが解決策を持っているなら、私もそれに興味があります。Dockerエントリーポイント機能が解決策を提供するかもしれないと思います。
RoboCop87 2018

0

データコンテナーを使用してその問題を解決しました。これには、アプリケーションレイヤーからデータを分離するという利点もあります。次のように実行できます。

docker run --volumes-from=<container-data-name> ubuntu

このチュートリアルでは、データコンテナの使用について説明します。


-1

私の状況では、問題は異なっていました。理由はわかりませんが、ホスト上のディレクトリがchmod 777実行されていても、Docker内ではと表示されていました755

コンテナ内で実行するとsudo chmod 777 my_volume_dir修正されました。


5
chmod 777ほとんど何も修正しません。
Erki Aring、

申し訳ありませんが、要点を逃しました。ポイントは、内側のコンテナーの特権が低くなり、外側から修正できないことです。
CodeSandwich

-2

sudo -s MACで私のためにトリックをしました


1
反対票を投じている場合は、コメントを残して理由を説明してください。まったく同じ問題が発生し、sudo -sでこれを解決できました。
Nachiket Joshi 2018

すべてのDockerイメージにsudoがあるわけではなく、すべてのシナリオでそれが可能であるとは限りません。
SOFe 2018

2
コンテナにsudoをインストールしないでください。攻撃者はコンテナ内でsudoを使用できます。
Arnold Balliu
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.