小ネタ&自分用のメモとして。
背景
Docker コンテナでデータを永続化するためにはボリュームが良く使われます。
ボリュームはホストのディレクトリをコンテナ内にマウントするものですが、それゆえにコンテナとホストの結びつきが強くなってしまいます。具体的にはコンテナを他のホストに持っていったときデータは永続化されません、データも一緒に移動するといったホスト側のメンテナンスが発生してしまいます。
また、複数ホスト間でコンテナを分散しクラスタリングしようとしたとき、やはりボリュームの一元化が必要という問題に悩まされることと思います。
ネットワークボリュームを使う事になると思うのですが、ホスト側にマウントする形ではホストのメンテナンス作業が発生してしまうので好ましくありません。
そこで Docker コンテナ内でネットワークボリュームをマウントできないかと考えました。
なぜ NFS でなく GlusterFS を選択したのかというと、NFS は(標準状態で)利用するポートが不定なためフィルタやフォワーディングが前提な環境だと使いにくかったというのが理由です。GlusterFS もクラスタ数で使用ポートが増えますがまだ設計や予測が可能な範疇だと思います。
要求
Docker コンテナ内で他のサーバーが提供している GlusterFS ボリュームをマウントしたい。
問題点
GlasterFS は FUSE を用いているがその仕組みが Docker のパーミッションに引っかかって利用ができない。
前提環境
GlasterFSサーバー = Debian8 マシン
Dockerホスト = 上記とは別の Debian8 マシン
Dockerコンテナ = Debian8
解決策
コンテナ起動時に FUSE が使うシステム要求を許可してやれば良いのです。
WEBで検索すると --privileged
スイッチをつけている例が多く見られます。実験確認用はこれでも良いかも知れないですが、全権限をコンテナに与えるのは些かの不安があるところですね。
必要な権限、とアクセス先のみに絞ると以下のスイッチのようになると思います。
--device=/dev/fuse --cap-add=SYS_ADMIN
準備
GlusterFS クライアントを含んだ Debian イメージを作成しておきます。
FROM debian:jessie
MAINTAINER rerofumi
RUN echo 'deb http://ftp.jp.debian.org/debian/ jessie main' > /etc/apt/sources.list
RUN echo 'deb http://security.debian.org/ jessie/updates main' >> /etc/apt/sources.list
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update; \
apt-get -y upgrade; \
apt-get -y dist-upgrade; \
apt-get -y install glusterfs-client; \
apt-get clean; \
rm -rf /var/lib/apt/lists/*
CMD ["/bin/bash"]
上記 Dockerfile を
docker build -t glusterfs-test .
などとしてテスト用イメージを作っておきましょう。
確認
テスト用イメージに、許可スイッチをつけて起動します。
docker run -it --device=/dev/fuse --cap-add=SYS_ADMIN --rm glustefs-test bash
コンテナが起動したら GlusterFS のボリュームをマウントしてみます。
mount -t glusterfs [GlusterFSサーバーのアドレス]:/[ボリューム名] /mnt
エラーが出ずにマウント完了したら成功です。