docker
dockerfile

docker-slimを使ってDockerイメージのダイエット

docker_global_hackday3_red.jpeg

背景

https://speakerdeck.com/stormcat24/oqian-falsedockerimezihamadazhong-i

上記のスライドを見て初めて1コンテナ1GBは重過ぎるということに気づかされました。
色々詰め込んでいるしあくまで趣味レベルで触っているだけでまあ良いかとずっと思ってましたが
業務でも触ることを考えて色々減量を考えました。
そんな中「docker-slim」が良いよって話を聞いて使ってみて想像以上に良かったのでご紹介。

公式HPは下記
http://dockersl.im/

Dockerイメージが大きい弊害

スライドの中からの引用です。
大きければビルドもアップロード/ダウンロード時間が増える。
当然のことですね。且つ待ち時間が多くなりTwitterする時間も確かに増えますね(笑)

  • イメージビルド、CI時間が増える
  • イメージのダウンロード時間が増える
  • イメージのアップロード時間が増える
  • 生産性が下がる
  • Twitterする時間が増える

減量方法

減量する方法は色々なところで議論されていますが主に下記が効果的

  • 軽量イメージを使用する (例:Alpineやscratch)
  • RUNをまとめる ()
  • マルチステージビルドを使う

マルチステージビルドは、Docker17.05以上で利用できる新機能です。
ビルドで使うコンテナと、最終的な実行可能ファイルだけを詰め込んだコンテナを
分けて使うことが出来ます。

それぞれしっかり調べていくと大量の時間がかかりますね。
そんな中上記を自動でやってくれるツール「docker-slim」がとても便利。

What is docker-slim ?

減量減量言ってましたがdocker-slimはコンテナの最適化ツールといった感じです。
ソースはGitHubで公開されています。ちなみに実装はGo。
スター数は2000程。最新バージョンは1.22で今もリリースされ続けています。
docker-slim/docker-slim

主な機能は下記。
最適化したDockerfileを作ってくれるので取り入れたい項目だけ使えたりするのは良いですね。

  • 静的及び動的解析による最適化
  • 最適化後にDockerfileを自動作成

インストール手順

MacとLinuxのバイナリーがREADMEのINSTALLATIONの欄にあります。
そちらを入手して解凍しパスを通すだけで使えるようです。
自前ビルド無しで使えるのはうれしいですね。
(ローカル構築の場合は手順が違うようなのでご注意を)

docker-slim [version|info|build|profile] [--http-probe|--remove-file-artifacts] <IMAGE_ID_OR_NAME>

色々オプションがありますが、基本的にはREADMEとDEMOの動画でことは足りる感触です。
実行例などでは主にサブコマンドを使って説明されている。

サブコマンド 説明
build 太ったイメージから軽量化されたイメージをビルド
profile コンテナレポートを作成
info 実行せずにDockerfileのみを作成
version docker-slimのバージョンを表示

使ってみた

環境

環境はこんな感じ
最新版のdocker-slimを取ってきて使ってます

$ uname -a
Linux ubuntu0827 4.15.0-39-generic #42-Ubuntu SMP Tue Oct 23 15:48:01 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
$ docker --version
Docker version 18.06.1-ce, build e68fc7a
サンプルDockerfile

使用するDockerfileはこんな感じ
とりあえず適当にJava入りコンテナを書いてみる。

Dockerfile
FROM ubuntu:latest

ENV JAVA_HOME /usr/lib/jvm/java-8-oracle

RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | debconf-set-selections && \
    apt-get update && \
    apt-get install -y software-properties-common && \
    add-apt-repository -y ppa:webupd8team/java && \
    apt-get update && \
    apt-get install -y oracle-java8-installer

CMD "/bin/bash"

導入

$ curl -L -O https://github.com/docker-slim/docker-slim/releases/download/1.22/dist_linux.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   607    0   607    0     0    988      0 --:--:-- --:--:-- --:--:--   986
100 5199k  100 5199k    0     0   366k      0  0:00:14  0:00:14 --:--:--  791k
$ tar zxvf dist_linux.tar.gz
dist_linux/
dist_linux/docker-slim
dist_linux/docker-slim-sensor
dist_linux  dist_linux.tar.gz  django_work  git-work  iog  kubernetes  omnibus-gitlab-master  python.py  work
$ cd dist_linux/
$ ls
docker-slim  docker-slim-sensor

導入したら太ったイメージを用意しdocker-slimを実行。
サンプル動画通りの動きです。

# 何もしないコンテナだけど844MB
$ docker images java_fat_1
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
java_fat_1          latest              c7c3170996a5        2 minutes ago       844MB

# docker-slimを実行したイメージ
$ docker images java_fat_1.slim
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
java_fat_1.slim     latest              e3607956321d        2 minutes ago       3.87MB

844MB ⇒ 3.87MBまで凄い圧縮率。
Dockerfileは.imagesにあるので中身を見てみます。
動的解析でインストール類が無くなってますね(例が悪かった←)
当然ですがコンテナ作ってからいろいろやろうとするなって話ですね

$ cat .images/c7c3170996a5c5a62e5544165a9dbd234e2139e5745eec1fc01948a2d2ea396f/artifacts/Dockerfile
FROM scratch
COPY files /
ENV PATH "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ENV JAVA_HOME "/usr/lib/jvm/java-8-oracle"
CMD ["/bin/sh","-c","\"/bin/bash\""]

まとめ

レイヤの結合だったりcacheの削除だったりやるべきことや学ぶべきことはたくさんある。
とりあえずAlpineLinuxだとかRUNの結合だ!とかやってましたがこの機会ににちょっとだけ知識が増えました。
今回紹介した減量ツールはその取っ掛かりとしてはとてもいいのでは無いでしょうか?
便利さゆえに本質を理解せずに使わないようにしたいですね。

自分もこんな感じの便利ツールで減量したい。。。

参考リンク

https://techblog.ca-wise.co.jp/2016/02/post-17.html
https://studygolang.com/articles/13233