自分でカスタマイズしたDockerイメージを作成しようと思って、オフィシャルのDockerファイルを読み込んでみると変わった処理が行われていることに気づいた。
以下はredis3.0のオフィシャルイメージの一部(Redisイメージ)
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
wget \
&& rm -rf /var/lib/apt/lists/*
基本的には余計なものは入れない、要件が終わると削除するという精神で作成を行っています。
--no-install-recommands
を使うと「推奨」パッケージをインストールせずに必要最低限の依存パッケージをインストールしてくれます。(推奨パッケージなんてあったんですね汗:余談ですが、よくapt-getとaptitudeの比較が挙げられていますが、aptitudeは推奨パッケージも自動で入れてくれるそうです。)
rm -rf /var/lib/apt/lists/*
キャッシュのようなファイルが置かれているそう
apt-get updateを実行すれば、新しく作成されるので削除しても問題ないということです。
http://unix.stackexchange.com/questions/217369/clear-apt-get-list
最後にまとめて削除すればいいんじゃない?と思うかもしれないのですが、
それではダメなんです
容量の大きなファイルを作成して、一行のRUNに収める場合と2行のRUNに収める場合で検証してみます。
Aパターン
FROM ruby:2.1.7
RUN dd if=/dev/zero of=/10megafile bs=1M count=10
RUN rm /10megafile
Bパターン
FROM ruby:2.1.7
RUN dd if=/dev/zero of=/10megafile bs=1M count=10 && rm /10megafile
Aからdocker build split .でイメージを作成
Bからdocker build same .でイメージを作成して、docker imagesで容量を確認します。
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
same latest bc928bf2446f 7 seconds ago 718.2 MB
split latest 53e3478f8d2d 2 minutes ago 728.7 MB
ちょうど10MBの差が確認できました。
このことからもわかるのですが、Dockerfileのコマンドはそれぞれレイヤーを作成します。
イメージの容量はすべてのレイヤーの合計になることがわかりました。
Dockerイメージがどのようなレイヤーで構成されているかは
docker history REPOSITORY
コマンドで見ることができます。
AパターンとBパターンでは
IMAGE CREATED CREATED BY SIZE COMMENT
53e3478f8d2d 8 minutes ago /bin/sh -c rm /10megafile 0 B
933d9d0cda06 8 minutes ago /bin/sh -c dd if=/dev/zero of=/10megafile bs= 10.49 MB
IMAGE CREATED CREATED BY SIZE COMMENT
bc928bf2446f 3 minutes ago /bin/sh -c dd if=/dev/zero of=/10megafile bs= 0 B
このような違いが出ます。
イメージのレイヤーをわかりやすく表示してくれるサービスもあるようです。
例えばredis3.0
https://imagelayers.io/?images=redis:3.0.0
あと、ひとつのRUNに詰め込みすぎじゃない?って思う方もいらっしゃると思いますが、これにも理由があって、レイヤーが127階層までしか作れないからだそうです。
まとめ
Dockerのイメージを軽くするためには、
- よけいなものをインストールしない
- 使ったら同じレイヤーの中で消す
ということでした。