こんにちは、鈴木です。
UnionFS をご存知でしょうか?
Docker を使い始めてから UnionFS の存在を知ったのですが、ちょっと面白い動きをするのでご紹介します。
UnionFS とは
UnionFS (Union FileSystem) を使用すると、複数のファイルシステムを一つの場所にマウントすることができます。
例えば、taro と jiro というディレクトリがあるとして、それぞれ以下のファイルを持っているとします。
1 2 3 4 |
taro/hoge taro/piyo jiro/fuga jiro/gofu |
これを hanako というディレクトリにまとめて、以下のように見せることができます。
1 2 3 4 |
hanako/hoge hanako/piyo hanako/fuga hanako/gofu |
UnionFS を使ってみる
以下は Ubuntu で試しました。unionfs-fuse というパッケージがあるので、これをインストールします。
1 |
sudo apt-get install unionfs-fuse |
次に taro と jiro というディレクトリを作成し、それぞれの中に適当なファイルを作成します。
1 2 3 4 5 |
mkdir taro jiro echo hoge > taro/hoge echo piyo > taro/piyo echo fuga > jiro/fuga echo gofu > jiro/gofu |
それではいよいよ、複数のディレクトリを一つのマウントポイントに束ねてみます。
hanako というディレクトリを作成し、そこに taro と jiro をマウントしてみましょう。
1 2 |
mkdir hanako unionfs-fuse taro=RW:jiro=RW hanako |
unionfs-fuse コマンドでマウントすることができます。引数は taro と jiro を一つにまとめて hanako にマウントする(どちらも RW=読み書き可能)という意味です。
tree コマンドで確認すると、taro と jiro が一つに束ねられて、hanako にマウントされたことが分かります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ tree . ├── hanako │ ├── fuga │ ├── gofu │ ├── hoge │ └── piyo ├── jiro │ ├── fuga │ └── gofu └── taro ├── hoge └── piyo 3 directories, 8 files |
読み書き可能としてマウントしたので、hanako ディレクトリ内のファイルを変更することができます。マウント時に「RW」ではなく「RO」を指定すれば、読み取り専用としてマウントすることができます。
それでは一度マウントを解除しましょう。
1 |
sudo umount hanako |
Copy on Write
次は Copy on Write を試してみましょう。
新しく changed というディレクトリを作成し、taro と jiro と changed をまとめて hanako にマウントします。ただし、taro と jiro は読み取り専用、changed だけ書き込み可能としてマウントします。
1 2 |
mkdir changed unionfs-fuse -o cow changed=RW:taro=RO:jiro=RO hanako |
この状態で各ディレクトリの内容を確認すると、以下のようになっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ tree . ├── changed ├── hanako │ ├── fuga │ ├── gofu │ ├── hoge │ └── piyo ├── jiro │ ├── fuga │ └── gofu └── taro ├── hoge └── piyo 4 directories, 8 files |
hanako/hoge の内容を変更してみましょう。
1 |
echo change! > hanako/hoge |
もう一度各ディレクトリの内容を確認すると、以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ tree . ├── changed │ └── hoge ├── hanako │ ├── fuga │ ├── gofu │ ├── hoge │ └── piyo ├── jiro │ ├── fuga │ └── gofu └── taro ├── hoge └── piyo 4 directories, 9 files |
そして各ディレクトリにあるファイル hoge の内容を確認すると、次のようになります。
1 2 3 4 5 6 |
$ cat hanako/hoge change! $ cat taro/hoge hoge $ cat changed/hoge change! |
hanako/hoge の内容を "change!" に変更したので hanako/hoge の内容が "change!" となっているのは当然ですが、元々の hoge ファイルがあった taro/hoge の内容を確認すると、変更前の "hoge" のままになっています。そして読み書き可能である changed ディレクトリに hoge というファイルが作成され、内容は "change!" になっています。
このように元のファイルは読み取り専用として、変更された場合は別のディレクトリ(今回は changed ディレクトリ)に変更されたファイルを保存させる、といったことが可能です。ファイルの移動や削除をした場合も、マウント元ディレクトリにあるファイルは変更されず、changed ディレクトリに変更されたファイルが現れます。
このような性質を利用すると、マウント元を変更させたくない or 読み取り専用メディアにあるので変更できない、という場合にも活用できそうです。
Docker の内部でこのような面白い技術が使われていると分かると、なんだか楽しくなってきますね。