Jaybanuan's Blog

どうせまた調べるハメになることをメモしていくブログ

コンテナで簡易NFSサーバを構築

はじめに

評価用にNFSサーバが必要になったため、コンテナで構築できないか調べてみた。

環境

$ cat /etc/os-release | grep PRETTY_NAME
PRETTY_NAME="Ubuntu 22.04 LTS"

$ uname -srvm
Linux 5.15.0-25-generic #25-Ubuntu SMP Wed Mar 30 15:54:22 UTC 2022 x86_64

$ docker version
Client: Docker Engine - Community
 Version:           20.10.14
(略)
Server: Docker Engine - Community
 Engine:
  Version:          20.10.14
(略)

利用したコンテナイメージ

DockerHubで公開されている以下を利用。

更新が2019年と古いが、NFSは枯れた技術なので数年前のものでも機能的には問題ないはず。

NFSサーバの構築

(1) ディレクトリの準備

まず、今回の調査の作業用として、ホスト側に以下のディレクトリを準備した。

/
`-- nfs
    `-- nfs-root

ホスト側の/nfs/nfs-rootを、コンテナ側の/exportにバインドマウントし、これをNFSで共有する。 ホスト側の/nfsは、後述するdocker-compose.ymlの配置場所にしている。

ディレクトリの作成のために、以下のコマンドを実行する。

$ sudo mkdir -p /nfs/nfs-root

また、後ほどNFSマウントができたかどうかを確認するために、/nfs/nfs-rootの中にファイルを一つ作成しておく。

$ sudo echo "hello, world!" > /nfs/nfs-root/greeting.txt

(2) docker-compose.ymlの作成

以下の内容でdocker-compose.ymlを作成し、/nfsに配置しておく。 一部ドキュメントどおりでは動かなかった部分があり手を加えているが、詳細は後述する。

version: "3.8"
services:
  "nfs-server":
    image: erichough/nfs-server
    privileged: true
#    cap_add:
#      - SYS_ADMIN
#      - SYS_MODULE
    ports:
      - "2049:2049"
    environment:
      NFS_EXPORT_0: "/export *(rw,sync,all_squash,no_subtree_check,fsid=0)"
    volumes:
      - /nfs/nfs-root:/export
      - /lib/modules:/lib/modules:ro

(3) NFSサーバの起動

以下のコマンドを実行して、NFSサーバのコンテナを起動する。

$ cd /nfs
$ docker-compose up -d

動作確認

(1) ホストからマウント

適当なディレクト/nfs-testを作成して、マウントを試してみる。

$ sudo apt update
$ sudo apt install nfs-common
$ sudo mkdir /nfs-test
$ sudo mount -v -t nfs4 [ホストマシンのIP]:/ /nfs-test

マウントに成功すると、以下のようにgreeting.txtを読み込むことができる。

$ cat /nfs-test/greeting.txt
hello, world!

(2) コンテナからマウント

まずはUbuntuのコンテナを起動する。 ネットワークはDocker Composeが作成したnfs_defaultを利用する。

$ docker run -it --privileged --net nfs_default ubuntu:latest /bin/bash

コンテナ起動後、コンテナの中に先ほどと同様に適当なディレクト/nfs-testを作成して、マウントを試してみる。

$ apt update
$ apt install nfs-common
$ mkdir /nfs-test
$ mount -v -t nfs4 nfs-server:/ /nfs-test

マウントに成功すると、以下のようにgreeting.txtを読み込むことができる。

$ cat /nfs-test/greeting.txt
hello, world!

ちなみに、コンテナ起動時にオプション--privilegedを付与しておかないと、以下のようなエラーが出てマウントに失敗する。

$ mount -t nfs4 nfs-server:/ /mnt
mount.nfs4: Operation not permitted

参考

ドキュメントどおりでは動かなかった部分

コンテナイメージerichough/nfs-serverのドキュメントは、ドキュメント内のリンクの都合上、DockerHubよりもGitHubの方を見たほうがよい。 主に次の2つのドキュメントを参照した。

github.com

github.com

ここで、コンテナに付与する権限について--privilegedではなく--cap-addを推奨しているが、ドキュメントどおりにSYS_ADMINSYS_MODULEを付与しても権限が足りずに起動に失敗する。 他に何が必要なのかを調べる時間がないので、--privilegedを利用した。

クライアント側でも--privilegedがないとマウントに失敗するので、NFSLinuxカーネルと密結合しているように思う。

NFSのバージョンについて

NFS v3はRPCやロックなどの様々なサービス(デーモン)を動的に組み合わせて実現しているため、設定が複雑で単にコンテナのポートをホスト側で公開するだけでは動かない。 そのため、コンテナでのNFS v3サーバの構築はハードルが高い。

一方、NFS v4はその辺りが改善されていて、ポート2049にアクセスできればNFSの利用が可能であり、コンテナでのNFS v4サーバの構築は比較的ハードルが低い。 とはいえ、--privileged等を利用した権限付与が必要であり、コンテナを運用する際のセキュリティポリシー次第では、NFS v4は利用できない可能性がある。