kakakakakku blog

Weekly Tech Blog : Keep on Learning 👍

Docker Experimental Features を有効化すると使える docker build の --squash オプション

Docker コンテナを本番運用する場合,コンテナイメージのサイズをできる限り小さくすることを意識すると思う.具体的には「レイヤー」を意識することにより,Dockerfile に記述する RUN を減らしたり,一時ファイルを消す場合に同じ RUNrm をする.最近だと「multi-stage builds」を使うこともできる.Dockerfile のベストプラクティスは,以下の公式ドキュメントに載っているし,最近では「Container Build Meetup」といったイベントもある.

docs.docker.com

docker build --squash とは?

Docker には「Docker Experimental Features」と呼ばれる仕組みがあり,有効化すると「実験的機能」を使えるようになる.現在だと「計6種類」の実験的機能があり,その中に docker build で使える --squash オプションがある.--squash オプションを使うと,自動的に「レイヤー」を1個に統合してくれるため,コンテナイメージのサイズを小さくできる.今回は --squash オプションを試すことにした.

Docker Experimental Features を有効化する

Docker for Mac の場合は Preferences の Daemon 画面から Experimental Features を有効化できる.

f:id:kakku22:20190619155418p:plain

一般的な Linux 環境の場合は /etc/docker/daemon.json に以下の JSON を定義し,Docker プロセスを再起動すると有効化できる.

{
    "experimental": true
}

有効化したら docker version コマンドで確認できる.有効化せずに --squash オプションを使うとエラーになる.

$ docker version -f '{{.Server.Experimental}}'
false

$ docker build --squash  .
"--squash" is only supported on a Docker daemon with experimental features enabled

$ docker version -f '{{.Server.Experimental}}'
true

検証 1 : Alpine をビルドする

まず,alpine:3.9FROM に指定した Dockerfile を作成する.

FROM alpine:3.9

kakakakakku/playground:v1 として docker build をすると,5.53MB になる.

$ docker build -t kakakakakku/playground:v1 .

$ docker images | egrep 'REPOSITORY|kakakakakku/playground' | sort
REPOSITORY                                                                  TAG                 IMAGE ID            CREATED             SIZE
kakakakakku/playground                                                      v1                  055936d39205        5 weeks ago         5.53MB

検証 2 : 一時ファイルを作成する

次に,dd30MB の一時ファイルを作成する手順を追加した Dockerfile を作成する.

FROM alpine:3.9
RUN dd if=/dev/zero of=file bs=1M count=30

kakakakakku/playground:v2 として docker build をすると,37MB になる.

$ docker build -t kakakakakku/playground:v2 .

$ docker images | egrep 'REPOSITORY|kakakakakku/playground' | sort
REPOSITORY                                                                  TAG                 IMAGE ID            CREATED             SIZE
kakakakakku/playground                                                      v1                  055936d39205        5 weeks ago         5.53MB
kakakakakku/playground                                                      v2                  57c261ac2dd3        11 seconds ago      37MB

検証 3 : 一時ファイルを別レイヤーで削除する

「検証 2」Dockerfile に一時ファイルを削除する手順を追加する.

FROM alpine:3.9
RUN dd if=/dev/zero of=file bs=1M count=30
RUN rm file

kakakakakku/playground:v3 として docker build をすると,同じく37MB になる.

$ docker build -t kakakakakku/playground:v3 .

$ docker images | egrep 'REPOSITORY|kakakakakku/playground' | sort
REPOSITORY                                                                  TAG                 IMAGE ID            CREATED             SIZE
kakakakakku/playground                                                      v1                  055936d39205        5 weeks ago         5.53MB
kakakakakku/playground                                                      v2                  57c261ac2dd3        42 seconds ago      37MB
kakakakakku/playground                                                      v3                  c54d6c94941b        10 seconds ago      37MB

docker history でレイヤーを確認すると,一時ファイルを作成するレイヤーと一時ファイルを削除するレイヤーが異なっている.よって,コンテナイメージのサイズは減らずに 37MB となる.

$ docker history kakakakakku/playground:v3
IMAGE               CREATED              CREATED BY                                      SIZE                COMMENT
c54d6c94941b        About a minute ago   /bin/sh -c rm file                              0B
57c261ac2dd3        2 minutes ago        /bin/sh -c dd if=/dev/zero of=file bs=1M cou…   31.5MB
055936d39205        5 weeks ago          /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>           5 weeks ago          /bin/sh -c #(nop) ADD file:a86aea1f3a7d68f6a…   5.53MB

検証 4 : 一時ファイルを同じレイヤーで削除する

今度は ddrm を同じ RUN の中で実行することにより,レイヤーを1個にした Dockerfile を作成する.

FROM alpine:3.9
RUN dd if=/dev/zero of=file bs=1M count=30 && \
    rm file

kakakakakku/playground:v4 として docker build をすると,一時ファイルが消えたことにより 5.53MB に戻った.ベストプラクティスに載っている方法と言える.

$ docker build -t kakakakakku/playground:v4 .

$ docker images | egrep 'REPOSITORY|kakakakakku/playground' | sort
REPOSITORY                                                                  TAG                 IMAGE ID            CREATED              SIZE
kakakakakku/playground                                                      v1                  055936d39205        5 weeks ago          5.53MB
kakakakakku/playground                                                      v2                  57c261ac2dd3        About a minute ago   37MB
kakakakakku/playground                                                      v3                  c54d6c94941b        43 seconds ago       37MB
kakakakakku/playground                                                      v4                  0d9323b479c5        7 seconds ago        5.53MB

検証 5 : --squash オプションを使う

最後に --squash オプションを試すため,「検証 3」と同じ Dockerfile を作成する.

FROM alpine:3.9
RUN dd if=/dev/zero of=file bs=1M count=30
RUN rm file

kakakakakku/playground:v5 として docker build --squash をすると,なんと 5.53MB になっている!

$ docker build --squash -t kakakakakku/playground:v5 .

$ docker images | egrep 'REPOSITORY|kakakakakku/playground' | sort
REPOSITORY                                                                  TAG                 IMAGE ID            CREATED              SIZE
kakakakakku/playground                                                      v1                  055936d39205        5 weeks ago          5.53MB
kakakakakku/playground                                                      v2                  57c261ac2dd3        About a minute ago   37MB
kakakakakku/playground                                                      v3                  c54d6c94941b        About a minute ago   37MB
kakakakakku/playground                                                      v4                  0d9323b479c5        45 seconds ago       5.53MB
kakakakakku/playground                                                      v5                  46bf29424020        16 seconds ago       5.53MB

docker history でレイヤーを確認すると,COMMENTmerge とあり,レイヤーが1個になっている.確かに --squash されている.

$ docker history kakakakakku/playground:v5
IMAGE               CREATED              CREATED BY                                      SIZE                COMMENT
46bf29424020        50 seconds ago                                                       0B                  merge sha256:c54d6c94941b40e8f54833c0404791482f541deebdad37fcc50456bd279562f6 to sha256:055936d3920576da37aa9bc460d70c5f212028bda1c08c0879aedf03d7a66ea1
<missing>           About a minute ago   /bin/sh -c rm file                              0B
<missing>           2 minutes ago        /bin/sh -c dd if=/dev/zero of=file bs=1M cou…   0B
<missing>           5 weeks ago          /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>           5 weeks ago          /bin/sh -c #(nop) ADD file:a86aea1f3a7d68f6a…   5.53MB

まとめ

  • 「Docker Experimental Features」を有効化すると「実験的機能」を使えるようになる
  • docker build で使える --squash オプションを試した
  • 一時ファイルの削除などを別レイヤーにしていても docker build のときにレイヤーを1個に統合できる