docker buildのsquashオプションを試す

# 目的
Docker 1.13で試験的に実装されたdocker buildのsquashオプションを試す。


# 環境

- Ubuntu 16.04
- docker 1.13.0


# 検証内容
dockerイメージのレイヤ構造をsquashを用いて統合することで、
途中で肥大化したdockerイメージを縮小できるかを試す。

# 検証

## ベースとなるでかいイメージを作る

昔作ったvncサーバのDockerfileを使う

```text:vncサーバのDockerfile
FROM centos:latest

ENV container docker
RUN yum update -y && yum clean all
RUN yum swap -y fakesystemd systemd && yum clean all
RUN yum groupinstall -y "Server with GUI" && yum clean all
RUN yum install -y tigervnc-server && yum clean all
ADD vncserver@:2.service /etc/systemd/system/
ADD vncserver@:3.service /etc/systemd/system/
ADD vncserver@:4.service /etc/systemd/system/
RUN systemctl enable vncserver@:2.service
RUN systemctl enable vncserver@:3.service
RUN systemctl enable vncserver@:4.service
RUN mkdir -p /root/.vnc
RUN echo password | /usr/bin/vncpasswd -f > /ro$ sudo docker build -f ./Dockerfile -t vnc_sample:latest `pwd`
ot/.vnc/passwd
RUN chmod 600 /root/.vnc/passwd
RUN echo password | passwd root --stdin
RUN systemctl disable firewalld
EXPOSE 5902 5903 5904
```

イメージをビルド

```bash:イメージのビルド
$ sudo docker build -f ./Dockerfile -t vnc_sample:latest `pwd`
```

```bash:構築されたイメージ
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
vnc_sample          latest              a2012410bb9a        3 seconds ago       2.58 GB
```

2.6 GBて...

## イメージのダイエット試行(squashなし)

```text:vncサーバからいろいろ削除するDockerfile
FROM vnc_sample:latest
RUN yum --setopt=tsflags=noscripts groupremove -y "Server with GUI
```

なんかyumがこけるので力づく。
今回は実用品ではないのでこれでよし。

```bash:ビルド(squshなし)
$ sudo docker build -f ./Dockerfile -t vnc_sample:without_squash `pwd`
```

### ダイエット結果

痩せるつもりが太ったぞ。
まあ、Dockerの仕組みを考えれば当然といえば当然...

```bash:ダイエット結果(squashなし)
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
vnc_sample          without_squash      a38e9e929b58        3 minutes ago       2.71 GB
vnc_sample          latest              a2012410bb9a        41 minutes ago      2.58 GB
```



## イメージのダイエット試行(squashあり)

ファイルはさっきのものと同じ。
```text:vncサーバからいろいろ削除するDockerfile
FROM vnc_sample:latest
RUN yum --setopt=tsflags=noscripts groupremove -y "Server with GUI
```

```bash:ビルド(squashあり)
$ sudo docker build --squash=true -f ./Dockerfile -t vnc_sample:with_squash `pwd`
```


### ダイエット結果(squashあり)

```bash:ダイエット結果
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
vnc_sample          with_squash         bfcf0227cb32        12 minutes ago      2.71 GB
vnc_sample          without_squash      a38e9e929b58        25 minutes ago      2.71 GB
```

あれ、変化なし...

# 変化無しの原因を調査

docker images inspectを調べると

```bash:image_inspectの結果
$ sudo docker image inspect vnc_sample:with_squash
[
    {
        "Id": "sha256:bfcf0227cb32a37536552212202daa62b475b4a03191756b2cb4a9c634d3296d",
        "RepoTags": [
            "vnc_sample:with_squash"
        ],
        "RepoDigests": [],
        "Parent": "",
        "Comment": "merge sha256:cabc99f1b570958260b5ede2a3b0166b87422439cb6b6ff591f4dcdf9762a575 to sha256:a2012410bb9a6f85d44720a98f3e64095ccf03934b356ce828b28919d1e46cfe",
        "Created": "2017-02-28T23:55:22.865535596+09:00",
        "Container": "732a1d6a7de0c2245a00288cc7cff6152bf9513d4dfac1391800cb34a27d322a",
        "ContainerConfig": {
            "Hostname": "1b0d6163fdc2",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "5902/tcp": {},
                "5903/tcp": {},
                "5904/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "container=docker"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "yum --setopt=tsflags=noscripts groupremove -y \"Server with GUI\""
            ],
            "ArgsEscaped": true,
            "Image": "sha256:a2012410bb9a6f85d44720a98f3e64095ccf03934b356ce828b28919d1e46cfe",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": [],
            "Labels": {
                "build-date": "20161214",
                "license": "GPLv2",
                "name": "CentOS Base Image",
                "vendor": "CentOS"
            }
        },
        "DockerVersion": "1.13.0",
        "Author": "",
        "Config": {
            "Hostname": "1b0d6163fdc2",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "5902/tcp": {},
                "5903/tcp": {},
                "5904/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "container=docker"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:a2012410bb9a6f85d44720a98f3e64095ccf03934b356ce828b28919d1e46cfe",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": [],
            "Labels": {
                "build-date": "20161214",
                "license": "GPLv2",
                "name": "CentOS Base Image",
                "vendor": "CentOS"
            }
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 2711258476,
        "VirtualSize": 2711258476,
        "GraphDriver": {
            "Name": "aufs",
            "Data": null
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:34e7b85d83e48a22bd5dfa2b6b9ee9565b7ef672f09b3d2409c61635f9bca4db",
                "sha256:c6b29ae49cee5a549734ac24ee29fcd645bd83d625c6ff9446d5b46e0280ca6e",
                "sha256:ca10b2c4746bd20991c29910da44689534f46b3209fb84d5baff66c3d606ee07",
                "sha256:a9f969e334cab422ce66ec8ef14ebc17486bdb4c9491f16678d1579d5d55a14b",
                "sha256:c729b315375f39eddd6518c0f4ba4466214f7ef5461a672fb26dd7f88eb5a170",
                "sha256:f2753206e61eb21ba8d49f659fad700dab4997f4de3355d24ac99a292327df1a",
                "sha256:a3af1c09ce22ef0d8c8322f9f3396646916d7014754e8ecdaaf612e0b0bb3340",
                "sha256:21b29e93469905ae822c483247e298c0ee85c2240ce11ac9660353f63b9fe9ec",
                "sha256:2e26beaf9707219a2af068082670390c01d13c6bb0854a8c1fcc3402a20a1ce8",
                "sha256:49ce464c98ca46b14937f6615fb846e594d02bf588e60f50f58b990468d2c328",
                "sha256:8a15f40d4a817fa091d50f08795b3def87f8d98ef679816a5a6468608ac0ad29",
                "sha256:c1bbbeeedb9f10c004dafe6a07e934c83e08391beec8e0a80d14393ef7f15f41",
                "sha256:8a3affc7f95e68f1ceebf533cc6ea6667e2ec733421c4ac0a7e44c0b009ef307",
                "sha256:d255871f2277f8cb715e1827820f6c389dc651016dd54c3861508dfe534f5a8e",
                "sha256:ac7ac7065a6fae8d1c88282d435c39b4741ca13267adc3e74e33a727b84b0f17",
                "sha256:7d63e80e3750dc310b5ae22132353d2ac5137ba719e86c5eb55e85f5307b504f",
                "sha256:195a002eb0a9952ae59270bfe2b06a08f4ee72974882eb0ecf8f05559ca0c656"
            ]
        }
    }
]

```

RootFSのLayersがおかしい。。。
ファイルシステムのレイヤ？がまとめられてない気が。

**ひょっとしてFROMで継承した部分はsquashでもまとめられない...?**

# 追加の検証内容

先ほどの2つのDockerfileをまとめてみた

```text:groupinstallして消すだけの悲しいDockerfile
FROM centos:latest


ENV container docker
RUN yum update -y && yum clean all
RUN yum swap -y fakesystemd systemd && yum clean all
RUN yum groupinstall -y "Server with GUI" && yum clean all
RUN yum install -y tigervnc-server && yum clean all
ADD vncserver@:2.service /etc/systemd/system/
ADD vncserver@:3.service /etc/systemd/system/
ADD vncserver@:4.service /etc/systemd/system/
RUN systemctl enable vncserver@:2.service
RUN systemctl enable vncserver@:3.service
RUN systemctl enable vncserver@:4.service
RUN mkdir -p /root/.vnc
RUN echo password | /usr/bin/vncpasswd -f > /root/.vnc/passwd
RUN chmod 600 /root/.vnc/passwd
RUN echo password | passwd root --stdin
RUN systemctl disable firewalld
EXPOSE 5902 5903 5904
RUN yum --setopt=tsflags=noscripts groupremove -y "Server with GUI"
```

でレッツビルド

```bash:squashつきでの再チャレンジ
$ sudo docker build --squash -f ./Dockerfile_squashed_kai -t vnc_sample:with_squash_kai `pwd`
```

```bash:dockerイメージの確認
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
vnc_sample          with_squash_kai     06dac317095e        35 seconds ago      1.39 GB
vnc_sample          with_squash        f249ccd0df34        11 minutes ago      2.71 GB
```

ふぁ〜ww、小さくなってる。どころ
**FROMで継承される親イメージの部分はsquashではまとめられないことがわかった**
(冷静に考えたらそうっちゃそうか...)

```bash:縮小できたイメージのinspect結果
$ sudo docker image inspect  vnc_sample:with_squash_kai
[
    {
        "Id": "sha256:06dac317095e2fca2ea1c1e0d30ef684caa7981290a22243a07cd23f0b126135",
        "RepoTags": [
            "vnc_sample:with_squash_kai"
        ],
        "RepoDigests": [],
        "Parent": "",
        "Comment": "merge sha256:5d1107bec7328cd5fa89189bd6435186133b21c82be9a7288a6603eed328a54a to sha256:67591570dd29de0e124ee89d50458b098dbd83b12d73e5fdaf8b4dcbd4ea50f8",
        "Created": "2017-03-01T00:16:29.808529481+09:00",
        "Container": "972a0f9939131f729531d1aad2bdd9066c1d99fab8c3fb4bc821abb41725a071",
        "ContainerConfig": {
            "Hostname": "1b0d6163fdc2",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "5902/tcp": {},
                "5903/tcp": {},
                "5904/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "container=docker"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "yum --setopt=tsflags=noscripts groupremove -y \"Server with GUI\""
            ],
            "ArgsEscaped": true,
            "Image": "sha256:a2012410bb9a6f85d44720a98f3e64095ccf03934b356ce828b28919d1e46cfe",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": [],
            "Labels": {
                "build-date": "20161214",
                "license": "GPLv2",
                "name": "CentOS Base Image",
                "vendor": "CentOS"
            }
        },
        "DockerVersion": "1.13.0",
        "Author": "",
        "Config": {
            "Hostname": "1b0d6163fdc2",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "5902/tcp": {},
                "5903/tcp": {},
                "5904/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "container=docker"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:a2012410bb9a6f85d44720a98f3e64095ccf03934b356ce828b28919d1e46cfe",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": [],
            "Labels": {
                "build-date": "20161214",
                "license": "GPLv2",
                "name": "CentOS Base Image",
                "vendor": "CentOS"
            }
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 1388248045,
        "VirtualSize": 1388248045,
        "GraphDriver": {
            "Name": "aufs",
            "Data": null
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:34e7b85d83e48a22bd5dfa2b6b9ee9565b7ef672f09b3d2409c61635f9bca4db",
                "sha256:24b25d102c50bd98f34aa6c8a40667bf79a8b660560f327f754e938f34044c96"
            ]
        }
    }
]
```

**RootFSのレイヤが減ってる。。。**

# まとめ

docker buildのsquashオプションでは以下の作用があることがわかった。

1. イメージサイズ縮小は実現できる
2. ただし、単一Dockerfile内のファイル削除のみが対象(親イメージは適用外)

# 所感

う〜ん、肥大化したイメージを継承してダイエットさせて使うことを
妄想したけれどもそれは実現できなさそう...
所詮はまだexperimentalなのか...?
誰かよさ気な使いどころを教えてくださいませ。

# 参考

- Docker 1.13のexperimental機能の有効化
    - http://qiita.com/RyoMa_0923/items/fc277336ef6ed6c7b3e4

- 今回使ったDockerfileのリポジトリ
    - https://github.com/Fufuhu/Dockerfile/tree/master/VNCServer