DockerコンテナでNFSのボリュームを利用する

はじめに

DockerコンテナでのNFSのボリュームを利用する手順を説明する。 ここでは、NFSサーバの情報は以下とする。

項目
IPアドレス 192.168.8.1
NFSのバージョン 4
公開ディレクト /shared

また、公開ディレクトリには、動作確認用にhello,world!という内容が書かれたファイルgreeting.txtを配置しておくことにする。

(1) ボリュームの作成

コンテナの起動に先立ち、「ボリューム」を作成しておく。

ボリュームとは、統一的なインタフェースで管理できるように、ストレージを抽象化したものである。 ボリュームの作成時に「ドライバ」を指定することで、様々なファイルシステムのボリュームを作成することができる。 Dockerがデフォルトで提供するlocalドライバは、実質的な処理をmountに委譲しているため、これを使えばNFSマウントは簡単に実現できる。

NFSのボリュームを作成するには、以下のコマンドを実行する。

$ docker volume create --driver local --opt type=nfs --opt o=addr=192.168.8.1,rw,nfsvers=4 --opt device=:/shared nfs-volume

上記のコマンドラインを見れば分かるように、オプション--optで指定できるドライバへのオプションはmountと同じである。

作成されたボリュームの情報を確認するには、以下のコマンドを実行する。

$ docker volume inspect nfs-volume
[
    {
        "CreatedAt": "2019-04-11T00:45:17+09:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/nfs-volume/_data",
        "Name": "nfs-volume",
        "Options": {
            "device": ":/shared",
            "o": "addr=192.168.8.1,rw,nfsvers=4",
            "type": "nfs"
        },
        "Scope": "local"
    }
]

(2) ボリュームのコンテナへのアタッチ

ボリュームをコンテナにアタッチする方法は、オプション--mountを利用する方法と、オプション--volumeを利用する方法の、2つがある。

オプション--mountを利用する場合は、以下のようになる。

$ docker run --mount source=nfs-volume,target=/shared -it ubuntu

また、オプション--volumeを利用する場合は、以下のようになる。

$ docker run --volume nfs-volume:/shared -it ubuntu

動作確認

ボリュームがアタッチされているかどうか確認する。 先の(2)の手順でubuntuを実行しているので、まずはコンテナの中からマウントの状態を確認する。

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay          98G   17G   77G  18% /
tmpfs            64M     0   64M   0% /dev
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
:/shared         98G   17G   77G  18% /shared
/dev/sda2        98G   17G   77G  18% /etc/hosts
shm              64M     0   64M   0% /dev/shm
tmpfs           2.0G     0  2.0G   0% /proc/asound
tmpfs           2.0G     0  2.0G   0% /proc/acpi
tmpfs           2.0G     0  2.0G   0% /proc/scsi
tmpfs           2.0G     0  2.0G   0% /sys/firmware

次に、同様にコンテナの中から動作確認用に作成しておいた/shared/greeting.txtの内容を表示できるか確認する。

$ cat /shared/greeting.txt
hello,world!

最後に、コンテナの外側からコンテナの情報を確認する。 オプション--mountを利用した場合は、以下のような結果となる。

$ docker inspect c60aa2108cc5
(略)
        "Mounts": [
            {
                "Type": "volume",
                "Name": "nfs-volume",
                "Source": "/var/lib/docker/volumes/nfs-volume/_data",
                "Destination": "/shared",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],
(略)

また、オプション--volumeを利用した場合は、以下のような結果となる。

$ docker inspect 98bfa1f78037
(略)
            "Mounts": [
                {
                    "Type": "volume",
                    "Source": "nfs-volume",
                    "Target": "/shared"
                }
            ],
(略)

補足: オプション--mount--volumeの違い

大雑把に言えば、アタッチしようとしているボリュームが存在しなかった時の挙動が違う。 オプション--volumeは古くからあるオプションであり、互換性を考慮すると、もはや挙動を変えることができないらしい。 そこで、オプション--volumeを残しつつも、オプション--mountを新設したとのこと。 そのため、今後は--mountを利用したほうが良い。

以降の説明では、NFSのボリュームについてのみ言及する。

オプション--mountの場合

オプション--mountの値には、ボリュームの作成に必要な各種情報を付け加えることができる。 ボリュームnfs-volumeがない状態で以下のようにコンテナを起動すると、NFSのボリュームが自動的に作成されて、それがコンテナにアタッチされる。

$ docker run --mount 'type=volume,source=nfs-volume,target=/shared,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/shared,"volume-opt=o=addr=192.168.8.1,rw,nfsvers=4"' -it ubuntu

作成されたボリュームの情報を表示すると、手順(1)で作成したものと同じであることが確認できる。

$ docker volume inspect nfs-volume
[
    {
        "CreatedAt": "2019-04-11T00:39:55+09:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/nfs-volume/_data",
        "Name": "nfs-volume",
        "Options": {
            "device": ":/shared",
            "o": "addr=192.168.8.1,rw,nfsvers=4",
            "type": "nfs"
        },
        "Scope": "local"
    }
]

オプション--volumeの場合

一方で、オプション--volumeにはボリュームを作成するための詳細情報を引き渡す手段がない。 ボリュームnfs-volumeがない状態で以下のようにコンテナを起動すると、NFSではなく「普通の」ホスト側のファイルシステムのボリュームが作成されて、それがコンテナにアタッチされる。

$ docker run --volume nfs-volume:/shared -it ubuntu

以下のように、コンテナの中からマウントの状況を確認すると、/sharedはマウントされているものの、NFSではないことが分かる。

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay          98G   17G   77G  18% /
tmpfs            64M     0   64M   0% /dev
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/sda2        98G   17G   77G  18% /shared
shm              64M     0   64M   0% /dev/shm
tmpfs           2.0G     0  2.0G   0% /proc/asound
tmpfs           2.0G     0  2.0G   0% /proc/acpi
tmpfs           2.0G     0  2.0G   0% /proc/scsi
tmpfs           2.0G     0  2.0G   0% /sys/firmware

そのため、コンテナの中には動作確認用のファイル/shared/greeting.txtは存在しない。

$ cat /shared/greeting.txt
cat: /shared/greeting.txt: No such file or directory

コンテナの外側から、以下のように作成されたボリュームの情報を確認すると、当然だがNFSの設定はなされていない。

$ docker volume inspect nfs-volume
[
    {
        "CreatedAt": "2019-04-14T23:36:16+09:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/nfs-volume/_data",
        "Name": "nfs-volume",
        "Options": null,
        "Scope": "local"
    }
]

参考