webdevqa.jp.net

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

一言で言えば、私は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です。

何がうまくいかないのですか?

218
user3753011

それはselinuxの問題です。

あなたは一時的に発行することができます

su -c "setenforce 0"

次のコマンドを実行してselinuxルールにアクセスするか追加します。

chcon -Rt svirt_sandbox_file_t /path/to/volume
223
user3761313

全文は このProject AtomicブログによるVolumesおよびSELinuxに関する投稿 を参照してください。

具体的には:

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

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

例えば:

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

Manページに記述されている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/dbが実行されます。ここでs0:c1,c2はコンテナごとに異なります。

211
gregswift

警告:この解決策にはセキュリティ上のリスクがあります。

コンテナを特権付きで実行してみます。

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

もう1つのオプション(私が試したことはない)は、特権付きコンテナーを作成してから、その中に非特権付きコンテナーを作成することです。

65
John Phillips

からaccess.redhat.com:Sharing_Data_Across_Containers

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

chcon -Rt svirt_sandbox_file_t Host_dir

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

それは回避策にすぎないようですが、私は試してみました、それはうまくいきます

29
Thomas8

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

これはオンです:

  • Dockerバージョン0.11.1-dev、ビルド02d20af/0.11.1
  • ホストとしてのcentos7とselinuxを有効にしたコンテナ。
12
jeff mccormick

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

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

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

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

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

SELinuxでのホストマウントの詳細については、 https://docs.docker.com/storage/#configure-the-selinux-label を参照してください。


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

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

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

開発者ごとにHost uid/gidが変わる可能性がある開発環境では、rootとして実行されているエントリポイントでコンテナを起動し、コンテナ内のユーザのuid/gidをHostボリュームのuid/gidと一致するように修正します。次にgosuを使用して、rootからコンテナユーザーにドロップし、コンテナ内でアプリケーションを実行します。このための重要なスクリプトは、私のベースイメージスクリプトのfix-permsです。 https://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を取得し、それらが一致しない場合は、UIDを調整するためにusermodを呼び出します。最後に、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のコンテナーがシフトされるため、ホストボリュームにはアクセス権の問題があることがわかります。そのシナリオでは、ホストボリュームを避け、名前付きボリュームのみを使用するのがおそらく最も簡単です。

7
BMitch

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/ のドキュメントを見てください。

5
cupen

私は同様の問題を抱えていました、私のものはホストの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に従ってコンテナとコマンドを実行すると、期待される結果が得られました。

3
RoboCop87

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

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

この チュートリアル はデータコンテナの使い方についての良い説明を提供します。

0
tmsss

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

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

0
CodeSandwich