Linuxでoverlayfsを使ってみる
初めまして、ALTURA X インターン生の藤嶋と申します。
今回は、Dockerについて学習を進めていく途中で、「imageはレイヤーになっており上から見た時に1つに見える」という説明が、実態としてどういう仕組なのかが分からなかったので、実際に手を動かしながらOverlayfsについてまとめてみました。
Overlayfsとは
まず、overlayfsとは何かについて説明していきます。
overlayfsは上と下の2つのディレクトリツリーを合体して1つのファイルシステムに見せる仕組みです。
dockerでは、変更を差分としてレイヤーごとに保存されます。そのため、それぞれのレイヤーにあたるディレクトリツリーを1つとして重ね合わせるためにoverlayfsが用いられています。
Overlayfsでは上の画像のように、lower01、lower02、upperディレクトリツリーを重ね合わせて、一つに見せます。
Overlayfsの動き
では、実際にコマンドを打ってどのような動きをするか確かめていきます。
まず、overlayfsを利用するためにディレクトリを作成してマウントを行います。
$ mkdir lower upper work merged
$ ls
get-docker.sh lower merged upper work
$ sudo mount -t overlay overlay -o lowerdir=lower,upperdir=upper,workdir=work merged\
upperが上の層でlowerが下の層になり、upperは読み書き可能でlowerはreadonlyとなります。
upperとlowerがマージされたものがmergedディレクトリ下にマウントされます。
moutコマンドを見てみると、
$ sudo mount -t [fsのタイプ] [device] -o [オプション] [mountポイント]
という形になっています。
deviceの所にoverlayと書かれていますが、これは物理的なデバイスではなく仮想的なファイルシステムが割り当てられます。
次に、lowerとupperディレクトリに直接ファイルを追加してみます。
$ echo "hoge" > upper/hoge.txt
$ echo "fuga" > lower/fuga.txt
$ ls upper
hoge.txt
$ ls lower
fuga.txt
ではこの時、mergedディレクトリはどうなるか確認しましょう。
$ ls merged
fuga.txt hoge.txt
mergedディレクトリ下には、先ほど作成したfuga.txtとhoge.txtの両方が表示されました。
これは、lowerディレクトリツリーとupperディレクトリツリーが重なり合され、透過的に上から見た状態として、一つのディレクトリツリーになったためです。
では、同じ名前のファイル名が上の層にも存在したときにmergedディレクトリでどのように表示されるのか確かめていきます。
$ echo "fuga2" > upper/fuga.txt
$ ls upper
fuga.txt hoge.txt
$ cat upper/hoge.txt
fuga2
upperディレクトリに直接fuga2と書かれたファイル、fuga.txtを追加しました。
この時、mergedディレクトリにはどのように表示されるのか確認していきます。
$ ls merged
fuga.txt hoge.txt
$ cat merged/fuga.txt
fuga2
再マウントをして、catコマンドで確かめてみるとfuga2と表示されました。
つまり、upperディレクトリに追加したfuga.txtが表示されています。
lowerとupperが重なり上から透過的に見た状態になるため、同じ名前のファイルがあった場合には上のファイルが表示されて、下のファイルは隠れて見えないようになります。
このようにovelayfsでは、上から透過的に見たディレクトリツリーとしてマージされ、同じ名前のファイルがあった場合には上の層にあるファイルが表示されます。
overlayfs上でのファイル操作
では、mergedディレクトリでファイルの追加、削除、更新を行ったとき、overlayfsではどのような動きをするか確認してみます。
ファイルの追加
まずはファイルの追加を行っていきたいと思います。
$ echo "piyo" > merged/piyo.txt
$ ls upper
fuga.txt hoge.txt piyo.txt
upperディレクトリにpiyo.txtが表示されました。
このことから、ファイルが追加されると読み書き可能なupperディレクトリに追加される事がわかりました。
ファイルの削除
次に、削除を行っていきます。
upperディレクトリは読み書き可能なので、ファイルを削除する事ができました。
では、Readonlyなlowerディレクトリ内のファイルを削除する場合はどうなるのか確認したいと思います。
$ echo "hogehoge" > lower/hogehoge.txt
$ umount merged
$ sudo mount -t overlay overlay -o lowerdir=lower,upperdir=upper,workdir=work merged\
まず、削除するファイルを作成してmergedディレクトリを再マウントします。
$ rm merged/hogehoge.txt
$ ls merged
hoge.txt fuga.txt piyo.txt
$ ls upper
fuga.txt hoge.txt piyo.tx hogehoge.txt
fuga.txtファイルを削除します。
この状態で、upperディレクトリを確認してみるとhogehoge.txtという作成したファイルと同じ名前のファイルが作成されていました。このファイルはホワイトアウトファイルという特別なファイルです。
lowerはReadonlyであるため、削除することができません。そのため、読み書き可能なupperに同名のホワイトアウトファイルを作成して、最終的には消えて見えるようにしています。
ファイルの更新
最後に更新を行います。
$ echo "fugafuga" > lower/fugafuga.txt
$ umount merged
$ sudo mount -t overlay overlay -o lowerdir=lower,upperdir=upper,workdir=work merged\
まず、更新するためのファイルをlowerディレクトリに追加し、同じように再マウントを行います。
$ echo "fugafuga2" > merged/fugafuga.txt
$ cat merged/fugafuga.txt
fugafuga2
$ ls upper
fuga.txt hoge.txt piyo.txt fugafuga.txt hogehoge.txt
$ cat upper/fugafuga.txt
fugafuga2
fugafuga.txtファイルの中身をfugafuga2に書き換えます。
その状態で、upperディレクトリの中を見てみると削除の場合と同じく、同じ名前のファイルが追加されました。
このファイルをcatコマンドで出力してみると、中身がfugafuga2であることがわかりました。
lowerはReadonlyで直接変更することができないため、読み書きできるupperにファイルのコピーを作成し、そのファイルを変更しています。
最終的には上の層のファイルが表示されるため、変更されているように見えます。
まとめ
今回は、dockerのimageの理解を進めるためにoverlayfsについて調べてみました。imageの仕組の説明を色々見ていた時はあまりピンと来なかったですが、実装としてdockerはlinuxのoverlayfsを利用していて、overlayfsがどのような動きをするかまで知れるようになると、自分の中でピンと来たような気がします。