Dockerと共有されるホストボリュームへのNFSディレクトリのマウント


8

次のDockerコンテナを検討してください。

docker run --rm -it -v /tmp:/mnt/tmp alpine sh

これにより、ホストディレクトリ/ tmpが高山コンテナ内の/ mnt / tmpにマウントされます。

次に、ホストシステムでNFSボリュームを/ tmpディレクトリにマウントします。

mkdir /tmp/nfs
mount -t nfs4 192.168.1.100:/data /tmp/nfs

マウントはホストシステムで機能し、次のように表示されます。

# ls /tmp/nfs
file1 file2 file3
#

しかし、Dockerコンテナでは、空のディレクトリが表示されます。

# ls /mnt/tmp/nfs
#

Dockerコンテナーで直接マウントすることで、これを回避できることを知っています。しかし、マウントがホストコンテナーでは機能するが、Dockerコンテナーでは機能しない理由を知りたいのですが、本当に興味がありますか?


OSやdockerのバージョンなどを説明する必要があるかもしれません。Centos7とdocker 1.10をエクストラから試してみましたが、期待どおりに動作しました。NFSマウントの内容は、debian / jessieコンテナー内に表示されました。また、セキュリティコントロール(SELinuxなど)やその他のフラグがあるかどうか。
スティーブンハリス

私はDockerバージョン1.12.0-devでUbuntu 16.04を使用していますが、追加のセキュリティコントロールはありません。この問題は、Alpineコンテナを作成した後でNFSマウントを作成したときにのみ発生します。Alpineコンテナーを作成する前にNFSマウントを作成すると、期待どおりに表示されます。
Caleb 2016年

回答:


15

これは、ボリュームがprivateマウント伝播を使用しているために発生します。つまり、マウントが行われると、起点側(Dockerの場合は「ホスト」側など)で行われた変更は、マウントの下に表示されなくなります。

これを処理する方法はいくつかあります。

  1. 最初にNFSマウントを実行してから、コンテナを起動します。マウントはコンテナーに伝達されますが、以前のように、マウントへの変更はコンテナーに表示されません(アンマウントを含む)。

  2. 「スレーブ」伝播を使用します。つまり、マウントが作成されると、オリジン側(dockerホスト)での変更は、ターゲット(コンテナー内)で確認できます。ネストされたマウントを実行している場合は、rslaver再帰的に)使用することをお勧めします。

「共有」伝播もあります。このモードでは、コンテナー内からマウントポイントに変更が加えられ、その逆も同様です。ユーザーにはそのような変更を行う権限さえないので(CAP_SYS_ADMINを追加しない限り)、これはおそらく望んでいることではありません。

次のようにマウントを作成するときに、伝播モードを設定できます。

$ docker run -v /foo:/bar:private

もう1つの方法は、ホストマウントではなくボリュームを使用することです。あなたはそうすることができます:

$ docker volume create \
    --name mynfs \
    --opt type=nfs \
    --opt device=:<nfs export path> \
    --opt o=addr=<nfs host> \
    mynfs
$ docker run -it -v mynfs:/foo alpine sh

これにより、常にコンテナにマウントされます。特定の方法でホストをセットアップしたり、マウントの伝播を処理したりする必要はありません。
:デバイスパスの前にが必要ですが、nfsカーネルモジュールについては奇妙なことです。
:Dockerは現在<nfs host>DNS名(1.13で対応予定)から解決しないため、ここでIPアドレスを指定する必要があります。

「共有サブツリー」マウントの詳細:https : //www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt


とても良い答えです。Docker DaemonでMountFlags = slaveを設定する方法を説明し、他の回答のコンテキストに依存しない、よりスタンドアロンの回答になるように編集してください。次に、これを承認された回答に切り替えます。
Caleb 2016年

4

ボリューム引数の最後に:sharedフラグを追加して、ボリュームで共有マウントの伝播を有効にします。

docker run --rm -it -v /tmp:/mnt/tmp:shared alpine sh

Dockerがパッケージマネージャーまたはsystemdのインストールスクリプトを介してインストールされた場合、MountFlagsデーモンの引数を調整する必要がある場合があります。これを行うには、docker.serviceファイルを探します。

$ sudo find /etc -name "docker.service"

私の場合、Ubuntu 16.04では/etc/systemd/system/multi-user.target.wants/docker.serviceにありました。このファイルをviまたはnanoで編集し、MountFlagsオプションが次のようになっていることを確認します。

MountFlags=shared

ファイルを保存し、デーモンの引数を再読み込みして、Dockerを再起動します。

$ sudo systemctl daemon-reload
$ sudo systemctl restart docker

これで、「docker run」を使用するときに、ボリュームに共有マウント伝播フラグを設定できるようになります。


3

docker 17.06以降、追加機能を必要とせずに、コンテナーを実行するときにNFS共有をコンテナーに直接マウントできます

export NFS_VOL_NAME=mynfs NFS_LOCAL_MNT=/mnt/mynfs NFS_SERVER=my.nfs.server.com NFS_SHARE=/my/server/path NFS_OPTS=vers=4,soft

docker run --mount \
  "src=$NFS_VOL_NAME,dst=$NFS_LOCAL_MNT,volume-opt=device=:$NFS_SHARE,\"volume-opt=o=addr=$NFS_SERVER,$NFS_OPTS\",type=volume,volume-driver=local,volume-opt=type=nfs" \
  busybox ls $NFS_LOCAL_MNT

または、コンテナの前にボリュームを作成することもできます。

docker volume create --driver local \
  --opt type=nfs --opt o=addr=$NFS_SERVER,$NFS_OPTS \
  --opt device=:$NFS_SHARE $NFS_VOL_NAME

docker run --rm -v $NFS_VOL_NAME:$NFS_LOCAL_MNT busybox ls $NFS_LOCAL_MNT

https://github.com/moby/moby/issues/28809からヒントを得ました

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.