今回のお題
今回はファイルを保存する際の方法の一つであるOverlayFS
の仕組み、およびDockerとの関わりについて取り上げます。
普段の開発ではあまり意識することのない部分かもしれませんが、個人的には非常に興味深い内容だったので1人でも多くの方に同じように感じていただけると幸いです。
なお、本記事で触れるのはあくまでも定性的かつ基本的な原理にとどめます。
実際にコードを打ってファイルを作って・・・とやっていると非常に長くなってしまうので、その点についてはご了承ください。
目次
- OverlayFSとは
- OverlayFSファイル作成時の動き
- OverlayFSファイル編集時の動き
- OverlayFSとDockerイメージ
OverlayFSとは
OverlayFSとはOverlay FileSystem
の略であり、Overlay、すなわち重ね合わせによってファイルの出力を管理するという方法です。
より具体的にいうと、OverlayFSで管理されているファイルはmergedir, workdir, upperdir, lowerdirという4つのディレクトリに分かれておりlowerdirとupperdirに存在するファイルを重ね合わせた内容がmergedir内に出力されて我々の目に触れることになります(workdirは作業に必要なリソースを保管するファイル)。
これだけでは分かりにくいと思うので、具体例を見てみましょう。
OverlayFSファイル作成時の動き
例として、hoge
とfuga
を出力するファイルを考えてみます。
このときのディレクトリ構成は以下のようになっています(あくまで一例です)。
|-- mergedir
|-- workdir
|-- upperdir
|-- lowerdir
|-- hoge.txt # hogeと出力
|-- fuga.txt # fugaと出力
```
hoge.txtとfuga.txtが実際に存在するのはlowerdirですが、見かけ上はmergedirに存在するように見えます。
```shell
% ls mergedir
>> hoge.txt fuga.txt
```
OverlayFSファイル編集時の動き
-
先程はファイル作成時の動きを説明しました。
では、このファイルに変更を加えた場合にはどのようになるでしょうか。
実は、この際にはlowerdir内のファイルが直接編集されることはありません。
編集前と編集後の差分だけが先述のupperdirに保存され、それがmergedirに読み取られることによって変更内容が反映されます。
例えば先程作成したファイルは`hoge fuga`と出力するようになっていますが、ここに`hogefuga`を追加する場合、以下のようになります。
```shell
|-- mergedir
|-- workdir
|-- upperdir
|-- hogefuga.txt # hogefugaと出力
|-- lowerdir
|-- hoge.txt # hogeと出力
|-- fuga.txt # fugaと出力
```
編集前はhoge.txtとfuga.txtのみを重ね合わせて表示していたのが、hogefuga.txtも含めた3つのファイルをmergeするように変わっています。
```shell
% ls mergedir
>> hoge.txt fuga.txt hogefuga.txt
```
また、今の例ではhogefugaという出力を追加しましたが、逆に出力を削除したり変更したりするとファイル構成は以下のように変わります。
今回は例として`hoge`の削除と`fuga`から`fugafuga`への変更をおこなっています。
```shell
|-- mergedir
|-- workdir
|-- upperdir
|-- hoge.txt # 何も出力しない
|------------------------- fuga.txt # fugafugaと出力
|-- lowerdir
|-- hoge.txt # hogeと出力
|------------------------- fuga.txt # fugaと出力
```
upperdirにhoge.txtとfuga.txtが出現していますね。
そしてlowerdirのhoge.txtとfuga.txt自体に変化はありません。
lowerdirのhoge.txtとfuga.txtの代わりにupperdirのそれらが読み取られることで、mergedirの中身が変わったように見せているというわけです。
### ファイルの読み取りの優先度について
今回のようにupperdirとlowerdirで同名のファイルが存在する場合にはupperdirが優先されます。
また、lowerdir内には複数のディレクトリを作成することも可能なのですが、その場合にもファイル名の衝突があれば上位のlowerdirが優先されます。
### ファイルを削除した場合の挙動について
OverlayFSにおいては、既存のファイルの上から何も出力しないファイルを上書きすることで元のファイルが消えたように見せています。
上記例ではhoge.txtを削除しましたが、この時に作成されたupperdir/hoge.txtはただのブランクファイルではなくホワイトアウトファイルと呼ばれる特別なファイルのようです。
OverlayFSとDockerイメージ
-
最後に、このOverlayFSがどのような場面で活かされているのかを解説します。
今回は例としてDockerイメージを取り上げます。
Dockerイメージを新しく作る場合、基本的にはベースイメージとそこに追加する内容をDockerfileに記述するかと思います。
この際にDockerイメージ内部ではベースイメージの情報をlowerdirに、追加した内容をupperdirに保存します。
このように部品ごとに分けておくと何が良いのかというと、ファイル容量の節約になるということです。
例えばcentos:centos7をベースイメージに、`/var/www/html`に`hoge.html`を追加した`centos_hoge`というDockerイメージを作成し、DockerHubにpushしたとします。
同じようにfuga.htmlを追加した`centos_fuga`も作成してpushしたとします。
もしDcokerイメージが部品ごとに分かれていない場合にはcentos_hogeとcentos_fugaの内容を丸々記録しておかなければなりませんが、ベースイメージはどちらもcentos:centos7なのでここが重複しているのはかなりの無駄です。
しかしパーツに分けて管理しておくことで、重複する部品は一つずつ保存すれば十分ということになります。
あとは誰かがイメージをpullした際には必要な部品をコピーしてOverlayFSファイルを作り、それを送信してあげればOKというわけです。