Dockerと共有されるホストボリュームにNFSディレクトリをマウントします。

Dockerと共有されるホストボリュームにNFSディレクトリをマウントします。

次の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コンテナでは動作しない理由を本当に知りたいです。

答え1

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

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

  1. NFSを最初にマウントしてコンテナを起動します。マウントはコンテナに伝播されますが、以前と同様に、マウントに対する変更(マウント解除を含む)はコンテナには表示されません。

  2. 「サブ」電波を使用します。つまり、マウントが作成されると、ソース(Dockerホスト)に対するすべての変更がターゲット(コンテナ)に表示されます。ネストしたインストールを実行する場合rslaver再帰)を使用することをお勧めします。

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

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

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

別のオプションは、ホストマウントの代わりにボリュームを使用することです。次のことができます。

$ 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

答え2

ボリュームパラメータの末尾に: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

関連情報