Docker コンテナを本番運用する場合,コンテナイメージのサイズをできる限り小さくすることを意識すると思う.具体的には「レイヤー」を意識することにより,Dockerfile
に記述する RUN
を減らしたり,一時ファイルを消す場合に同じ RUN
で rm
をする.最近だと「multi-stage builds」を使うこともできる.Dockerfile
のベストプラクティスは,以下の公式ドキュメントに載っているし,最近では「Container Build Meetup」といったイベントもある.
docker build --squash
とは?
Docker には「Docker Experimental Features」と呼ばれる仕組みがあり,有効化すると「実験的機能」を使えるようになる.現在だと「計6種類」の実験的機能があり,その中に docker build
で使える --squash
オプションがある.--squash
オプションを使うと,自動的に「レイヤー」を1個に統合してくれるため,コンテナイメージのサイズを小さくできる.今回は --squash
オプションを試すことにした.
Docker Experimental Features を有効化する
Docker for Mac の場合は Preferences の Daemon 画面から Experimental Features を有効化できる.
一般的な 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.9
を FROM
に指定した 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 : 一時ファイルを作成する
次に,dd
で 30MB
の一時ファイルを作成する手順を追加した 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 : 一時ファイルを同じレイヤーで削除する
今度は dd
と rm
を同じ 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
でレイヤーを確認すると,COMMENT
に merge
とあり,レイヤーが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個に統合できる