Overlay2 について調べてみた


作業時のメモ

Docker の StorageDriver の一つである Overlay2 について調べた・動きを検証したときのメモ。

# どういう仕組み？

Overlay2/Overlay は OverlayFS という仕組みを利用している

[実践! OverlayFS](https://qiita.com/awakia/items/af9b46c322905cdce1d7)


>OverlayFSの基礎
>ドキュメントには色々書いているが、Overlayfsの基本的な考え方は以下の通り
>    Readonlyな下の層と、Writableな上の層を重ね合わせ1つのファイルシステムに見せる
>    このとき、ディレクトリは重ね合わされ、ファイルは上から見ていく
>        コンフリクトしていたらファイルだと上が優先され、ディレクトリだとマージされる
>    下(readonly)にしかないファイルを編集すると上にコピーが作成される


Docker の公式ページにも Overlay/Overlay2 の説明がある
イメージ図があるが Overlay のものなので注意。

[Use the OverlayFS storage driver](https://docs.docker.com/storage/storagedriver/overlayfs-driver/)

>The overlay2 driver natively supports up to 128 lower OverlayFS layers. This capability provides better performance for layer-related Docker commands such as docker build and docker commit, and consumes fewer inodes on the backing filesystem.

上記ドキュメントにも記載があるが overlay2 は複数の lower layer をサポートしている。
利用イメージ例は以下のようになる

[Container Storage Best Practices in 2017 p21](https://www.slideshare.net/KeithResar/container-storage-best-practices-in-2017#21)

これを見るとイメージがしやすい。
上記にそれぞれの StorageDriver の　Pros/Cons も書いてある。

# 動きを検証

## 環境

```bash
docker info
Containers: 42
 Running: 4
 Paused: 0
 Stopped: 38
Images: 26
Server Version: 18.06.1-ce
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 468a545b9edcd5932818eb9de8e72413e616e86e
runc version: 69663f0bd4b60df09991c08812a60108003fa340
init version: fec3683
Security Options:
 seccomp
  Profile: default
Kernel Version: 4.14.77-80.57.amzn2.x86_64
Operating System: Amazon Linux 2
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 985.7MiB
Name: ip-172-31-30-50.ap-northeast-1.compute.internal
ID: M5OF:USUI:CHU4:NPLX:6TPC:DJ52:6C6O:DEHT:2BUM:WDHN:DSCO:HFHD
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

```

# コンテナを作る

```bash
$docker run -d alpine sleep 10000
8c22dfe56161d277ffe02bef504848a88ec759c7d28d4259570a25f4401b04a6

# 配置場所を確認
$docker inspect 8c22dfe56161 |less

        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff:/var/lib/docker/overlay2/b88590da7d8e2e35c9b4f7368017760575b71c95f5ff68b7ee8dfc86f9fc7a66/diff",
                "MergedDir": "/var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/merged",
                "UpperDir": "/var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/diff",
                "WorkDir": "/var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/work"
            },
            "Name": "overlay2"
        },
```

## LowerDir 

LowerDir は2つなので Layer は2つということだと思われる

+ /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff
+ /var/lib/docker/overlay2/b88590da7d8e2e35c9b4f7368017760575b71c95f5ff68b7ee8dfc86f9fc7a66/diff


Alphine の Dockerfile

[alpinelinux/docker-alpine](https://github.com/alpinelinux/docker-alpine/blob/da78fcf5c5da55092aa82a97095274b3df648866/x86_64/Dockerfile)

```
FROM scratch
ADD alpine-minirootfs-3.10.2-x86_64.tar.gz /
CMD ["/bin/sh"]
```

確かに2つぽい

それぞれ見てみる

```bash
$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff/
dev  etc

$sudo ls /var/lib/docker/overlay2/b88590da7d8e2e35c9b4f7368017760575b71c95f5ff68b7ee8dfc86f9fc7a66/diff/
bin  etc   lib    mnt  proc  run   srv  tmp  var
dev  home  media  opt  root  sbin  sys  usr
```

Github から 「alpine-minirootfs-3.10.2-x86_64.tar.gz」を落とすと「/var/lib/docker/overlay2/b88590da7d8e2e35c9b4f7368017760575b71c95f5ff68b7ee8dfc86f9fc7a66/diff/」と同じ構成だった。

別のコンテナでも確認してみる。

[超軽量 Docker Image true (125 bytes) と sleeping-beauty (129 bytes)](https://qiita.com/kitsuyui/items/ba6eb17e6bbe97aa6b04)


```bash
$docker run -d tianon/sleeping-beauty

$ docker inspect d00b12c14095 |less

        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b-init/diff:/var/lib/docker/overlay2/4e31a13b0f9f31f90d2dc4a5c19d5f4e87788fefb29e8b550005ba4a984ca4f6/diff",
                "MergedDir": "/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/merged",
                "UpperDir": "/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/diff",
                "WorkDir": "/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work"
            },
            "Name": "overlay2"
        },

$sudo ls /var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b-init/diff
dev  etc  proc  sys

$sudo ls /var/lib/docker/overlay2/4e31a13b0f9f31f90d2dc4a5c19d5f4e87788fefb29e8b550005ba4a984ca4f6/diff
sleeping-beauty
```

Dockerfile　はこうなっていた

```
FROM scratch
COPY sleeping-beauty /
CMD ["/sleeping-beauty"]
```

「-init 」というのは scratch ということで良さそうだが差分が有るのは Dockerhub に Push された際の scratch の構成の違いなのかも。

## UpperDir

コンテナは起動しただけで container layer(read/write)には何も書き込みをしていないので空っぽ。

```bash
$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/diff/
```

## WorkDir 

work というフォルダがあるぐらいで空っぽ

```bash
sudo tree /var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work/
/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work/
`-- work

1 directory, 0 files
```

## MergedDir 

alphine コンテナ。

```bash
$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/merged/
bin  etc   lib    mnt  proc  run   srv  tmp  var
dev  home  media  opt  root  sbin  sys  usr
```

「sleeping-beauty」の方が分かりやすいのでこちらも確認。

```bash
sudo ls /var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/merged/
dev  etc  proc  sleeping-beauty  sys
```

LowerDir の Scratch の Layer のファイルに sleeping-beatuty が追加されている。


# コンテナにファイルを作る

コンテナにファイルを作ってどうなるか変化を見てみる。
先程起動した alphine コンテナを利用する。


```bash
# コンテナにファイルを作成
$docker exec 8c22dfe56161 touch /tmp/hoge

# UpperDir に追加されている
$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/diff/tmp/
hoge

# MergedDir にも確認出来る
$ sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/merged/tmp/
hoge

```

# コンテナを停止する

コンテナを停止させる。

```bash
# 停止
$docker stop 8c22dfe56161
8c22dfe56161

# SIGKILL で止まって終了ステータスコード 137 ぽい
$docker ps -a |grep 8c22dfe56161
8c22dfe56161        alpine                           "sleep 10000"            34 minutes ago       Exited (137) 25 seconds ago                         reverent_leavitt

# LowerDir はある
$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff/
dev  etc

# UpperDir はある
$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/diff/tmp/

# MergedDir はなくなる
$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/merged/
37b389953f47451e38e89dd37/merged/: No such file or directory

# WorkedDir もある
sudo tree /var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work/
/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work/
`-- work

1 directory, 0 files
```

# コンテナを削除する

```bash
$docker rm 8c22dfe56161

# 全部消えた
sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff/

$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff/
ls: cannot access /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff/: No such file or directory

$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/diff/tmp/
ls: cannot access /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/diff/tmp/: No such file or directory

$sudo tree /var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work/
/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work/
`-- work

1 directory, 0 files


```