通常、ホストボリュームマウントの権限の問題は、コンテナ内の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-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を取得し、それらが一致しない場合は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がシフトされるため、ホストボリュームに権限の問題があることがわかります。そのシナリオでは、ホストボリュームを避け、名前付きボリュームのみを使用するのがおそらく最も簡単です。