次のDockerコンテナを検討してください。
docker run --rm -it -v /tmp:/mnt/tmp Alpine sh
これにより、ホストディレクトリ/ tmpがAlpineコンテナー内の/ 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コンテナーでは機能しない理由を知りたいのですが、本当に興味がありますか?
これは、ボリュームがprivate
マウント伝播を使用しているために発生します。つまり、マウントが行われると、Origin側(Dockerの場合は「ホスト」側など)で行われた変更はマウントの下に表示されなくなります。
これを処理する方法はいくつかあります。
最初にNFSマウントを実行してから、コンテナーを開始します。マウントはコンテナーに伝達されますが、以前のように、マウントへの変更はコンテナーに表示されません(アンマウントを含む)。
「スレーブ」伝播を使用します。つまり、マウントが作成されると、Origin側(docker Host)での変更は、ターゲット(コンテナー内)で確認できるようになります。ネストされたマウントを実行している場合は、rslave
(再帰的な場合はr
)を使用する必要があります。
「共有」伝播もあります。このモードでは、コンテナー内からマウントポイントに変更が加えられ、その逆も同様です。ユーザーにはそのような変更を行う権限さえないので(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カーネルモジュールについては奇妙なことです。
note:Dockerは現在解決しません<nfs Host>
DNS名から(1.13で対応予定)、IPアドレスをここで指定する必要があります。
「共有サブツリー」マウントの詳細: https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt
ボリューム引数の最後に: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」を使用するときに、ボリュームに共有マウント伝播フラグを設定できるはずです。
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 からヒントを得ました