一言で言えば、私は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です。
何がうまくいかないのですか?
それはselinuxの問題です。
あなたは一時的に発行することができます
su -c "setenforce 0"
次のコマンドを実行してselinuxルールにアクセスするか追加します。
chcon -Rt svirt_sandbox_file_t /path/to/volume
全文は この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
はコンテナごとに異なります。
警告:この解決策にはセキュリティ上のリスクがあります。
コンテナを特権付きで実行してみます。
Sudo docker run --privileged=true -i -v /data1/Downloads:/Downloads ubuntu bash
もう1つのオプション(私が試したことはない)は、特権付きコンテナーを作成してから、その中に非特権付きコンテナーを作成することです。
からaccess.redhat.com:Sharing_Data_Across_Containers :
ホストボリュームの設定は、ホストに依存し、他のどのマシンでも機能しない可能性があるため、移植性がありません。このため、HostディレクトリをコンテナにマウントするためのDockerfileに相当するものはありません。また、ホストシステムにはコンテナSELinuxポリシーに関する知識がないことにも注意してください。したがって、SELinuxポリシーが適用されていると、rwの設定に関係なく、マウントされたHostディレクトリはコンテナに書き込みできません。現在、適切なSELinuxポリシータイプをホストディレクトリに割り当てることでこれを回避することができます。 ":
chcon -Rt svirt_sandbox_file_t Host_dir
Host_dirは、コンテナにマウントされているホストシステム上のディレクトリへのパスです。
それは回避策にすぎないようですが、私は試してみました、それはうまくいきます
chcon -Rt svirt_sandbox_file_t /path/to/volume
が機能することを確認しました。特権コンテナとして実行する必要はありません。
これはオンです:
通常、ホストボリュームマウントに関するアクセス権の問題は、コンテナ内の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のコンテナーがシフトされるため、ホストボリュームにはアクセス権の問題があることがわかります。そのシナリオでは、ホストボリュームを避け、名前付きボリュームのみを使用するのがおそらく最も簡単です。
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/ のドキュメントを見てください。
私は同様の問題を抱えていました、私のものはホストの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に従ってコンテナとコマンドを実行すると、期待される結果が得られました。
データコンテナを使用してこの問題を解決しました。これには、データをアプリケーション層から分離するという利点もあります。あなたはこのように実行することができます:
docker run --volumes-from=<container-data-name> ubuntu
この チュートリアル はデータコンテナの使い方についての良い説明を提供します。
私の状況では問題は異なっていました。理由はわかりませんが、Host上のディレクトリにchmod 777
が実行されていても、docker内では755
として表示されていました。
コンテナSudo chmod 777 my_volume_dir
内で実行することで修正されました。