概要
Dockerイメージのサイズが大きくなるとレジストリにPushやPullする時間が増します
運用環境や開発環境でイメージのやり取りを繰り返される場合は、回数を重ねるごとにバカにならないほどの待ち時間が発生することになる
また、ネットワーク帯域も無駄に消費します
なので、簡単にできるイメージサイズのダウンサイジングをご紹介します
下記のサンプルでは1.04GBのイメージ ⇒ 415MBまでにダウンサイジングしています
もし、下記以外にもダウンサイジングの方法がありましたら、ご教示ください!
以下のサンプルコードでは、差を分かりやすくするためにあえてjdkをダウンロードし、所有権を変更しています
なお、イメージのリビルド時にキャッシュの有効利用は考慮していません
おさらい
Dockerイメージはビルド時にDockerfileの各コマンドごとに中間イメージが作成される
各中間イメージにはそのコマンドで実行された変更履歴が含まれます
各コマンドが実行され、生成された中間イメージは以下のようになります
最適化していない状態
まず、なにも最適化していないDockerfileでビルドされたイメージサイズは1.04GBもあります!
FROM node:12-slim
WORKDIR /tmp
RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz
RUN tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz
RUN chown node:node -R /tmp/jdk-12.0.2/
RUN apt-get update -y
RUN apt-get upgrade -y
historyコマンドで中間イメージの容量を確認していきましょう
jdkの取得やファイル解凍で容量を消費しているのはわかりやすいのですが、
chownのようにファイルのメタデータ(所有権)の変更分も容量を消費します
ここは案外見落としがちなポイントです
> docker build -t downsize:1 ./
-----------------------------------------------------------------------------------------------------------
REPOSITORY TAG IMAGE ID CREATED SIZE
downsize 1 e7d7b8b217ba About a minute ago 1.04GB
> docker history downsize:1
-----------------------------------------------------------------------------------------------------------
IMAGE CREATED CREATED BY SIZE
e7d7b8b217ba 2 minutes ago /bin/sh -c apt-get upgrade -y 3.85MB
f70cff27b81a 2 minutes ago /bin/sh -c apt-get update -y 16.4MB
ce460fc686bc 2 minutes ago /bin/sh -c chown node:node -R /tmp/jdk-12.0.… 335MB
29b8fb0905ac 2 minutes ago /bin/sh -c tar -zxvf ./openjdk-12.0.2_linux-… 335MB
39545720b094 3 minutes ago /bin/sh -c wget https://download.java.net/ja… 198MB
48b8f4c4641a 3 minutes ago /bin/sh -c #(nop) WORKDIR /tmp 0B
710340b3b82e 2 months ago /bin/sh -c #(nop) CMD ["node"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B
<missing> 2 months ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B
<missing> 2 months ago /bin/sh -c set -ex && for key in 6A010… 5.08MB
<missing> 2 months ago /bin/sh -c #(nop) ENV YARN_VERSION=1.16.0 0B
<missing> 2 months ago /bin/sh -c buildDeps='xz-utils' && ARCH=… 90.4MB
<missing> 2 months ago /bin/sh -c #(nop) ENV NODE_VERSION=12.6.0 0B
<missing> 2 months ago /bin/sh -c groupadd --gid 1000 node && use… 333kB
<missing> 2 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ADD file:5ffb798d64089418e… 55.3MB
コマンドをまとめる
各コマンドをすべてひとつのRUN
にまとめることで一連のコマンドで発生した履歴も1つになる
中間イメージが減る分容量消費も抑えられる
結果的に300MB減の704MBになりました
FROM node:12-slim
WORKDIR /tmp
RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz \
&& tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz \
&& chown node:node -R /tmp/jdk-12.0.2/ \
&& apt-get update -y \
&& apt-get upgrade -y
> docker build -t downsize:2 ./
-----------------------------------------------------------------------------------------------------------
REPOSITORY TAG IMAGE ID CREATED SIZE
downsize 2 30a607b1a778 About a minute ago 704MB
> docker history downsize:2
-----------------------------------------------------------------------------------------------------------
IMAGE CREATED CREATED BY SIZE
30a607b1a778 2 minutes ago /bin/sh -c wget https://download.java.net/ja… 553MB
48b8f4c4641a 7 minutes ago /bin/sh -c #(nop) WORKDIR /tmp 0B
710340b3b82e 2 months ago /bin/sh -c #(nop) CMD ["node"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B
<missing> 2 months ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B
<missing> 2 months ago /bin/sh -c set -ex && for key in 6A010… 5.08MB
<missing> 2 months ago /bin/sh -c #(nop) ENV YARN_VERSION=1.16.0 0B
<missing> 2 months ago /bin/sh -c buildDeps='xz-utils' && ARCH=… 90.4MB
<missing> 2 months ago /bin/sh -c #(nop) ENV NODE_VERSION=12.6.0 0B
<missing> 2 months ago /bin/sh -c groupadd --gid 1000 node && use… 333kB
<missing> 2 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ADD file:5ffb798d64089418e… 55.3MB
一時ファイルを削除する
これも忘れがちですが、一時ファイルを削除するだけでサイズ減に繋がる
上記のコマンドに rm -f ./openjdk-12.0.2_linux-x64_bin.tar.gz
を追加しただけで、
さらに200MB減の506MBになりました
FROM alpine
WORKDIR /tmp
RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz \
&& tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz \
&& chown postgres:postgres -R /tmp/jdk-12.0.2/ \
&& rm -f ./openjdk-12.0.2_linux-x64_bin.tar.gz
openjdk-12.0.2_linux-x64_bin.tar.gz分のサイズが減った!
> docker build -t downsize:3 ./
-----------------------------------------------------------------------------------------------------------
REPOSITORY TAG IMAGE ID CREATED SIZE
downsize 2 92986480403b About a minute ago 506MB
> docker history downsize:3
-----------------------------------------------------------------------------------------------------------
IMAGE CREATED CREATED BY SIZE
92986480403b 4 seconds ago /bin/sh -c wget https://download.java.net/ja… 355MB
48b8f4c4641a 9 minutes ago /bin/sh -c #(nop) WORKDIR /tmp 0B
710340b3b82e 2 months ago /bin/sh -c #(nop) CMD ["node"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B
<missing> 2 months ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B
<missing> 2 months ago /bin/sh -c set -ex && for key in 6A010… 5.08MB
<missing> 2 months ago /bin/sh -c #(nop) ENV YARN_VERSION=1.16.0 0B
<missing> 2 months ago /bin/sh -c buildDeps='xz-utils' && ARCH=… 90.4MB
<missing> 2 months ago /bin/sh -c #(nop) ENV NODE_VERSION=12.6.0 0B
<missing> 2 months ago /bin/sh -c groupadd --gid 1000 node && use… 333kB
<missing> 2 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ADD file:5ffb798d64089418e… 55.3MB
これだと減らないので注意!
コマンドを分けることでIMAGE ID:30a607b1a778
の結果は553MBのままなので、そのまま中間イメージとして加算される
FROM node:12-slim
WORKDIR /tmp
RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz \
&& tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz \
&& chown node:node -R /tmp/jdk-12.0.2/ \
&& apt-get update -y \
&& apt-get upgrade -y
RUN rm -f ./openjdk-12.0.2_linux-x64_bin.tar.gz
> docker build -t downsize:3.1 ./
-----------------------------------------------------------------------------------------------------------
REPOSITORY TAG IMAGE ID CREATED SIZE
downsize 3.1 4ee2a610be24 About a minute ago 704MB
> docker history downsize:3.1
-----------------------------------------------------------------------------------------------------------
IMAGE CREATED CREATED BY SIZE
4ee2a610be24 About a minute ago /bin/sh -c rm -f ./openjdk-12.0.2_linux-x64_… 0B
30a607b1a778 8 minutes ago /bin/sh -c wget https://download.java.net/ja… 553MB
48b8f4c4641a 13 minutes ago /bin/sh -c #(nop) WORKDIR /tmp 0B
710340b3b82e 2 months ago /bin/sh -c #(nop) CMD ["node"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B
<missing> 2 months ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B
<missing> 2 months ago /bin/sh -c set -ex && for key in 6A010… 5.08MB
<missing> 2 months ago /bin/sh -c #(nop) ENV YARN_VERSION=1.16.0 0B
<missing> 2 months ago /bin/sh -c buildDeps='xz-utils' && ARCH=… 90.4MB
<missing> 2 months ago /bin/sh -c #(nop) ENV NODE_VERSION=12.6.0 0B
<missing> 2 months ago /bin/sh -c groupadd --gid 1000 node && use… 333kB
<missing> 2 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ADD file:5ffb798d64089418e… 55.3MB
マルチステージング化
今回のサンプルでは残念ながらサイズ減にはならなかったが、
中間イメージサイズの起算が COPY --from=base /tmp/jdk-12.0.2 /tmp/jdk-12.0.2
になりますので、
事前処理であれこれ(ソースのコンパイルなど)した場合は、マルチステージング化することで簡単に容量減に繋がります
FROM node:12-slim as base
WORKDIR /tmp
RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz \
&& tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz \
&& chown node:node -R /tmp/jdk-12.0.2/
FROM node:12-slim
COPY --from=base /tmp/jdk-12.0.2 /tmp/jdk-12.0.2
RUN apt-get update -y \
&& apt-get upgrade -y
> docker build -t downsize:4 ./
-----------------------------------------------------------------------------------------------------------
REPOSITORY TAG IMAGE ID CREATED SIZE
downsize 4 593b49b2ed5e About a minute ago 506MB
> docker history downsize:4
-----------------------------------------------------------------------------------------------------------
IMAGE CREATED CREATED BY SIZE
593b49b2ed5e 12 minutes ago /bin/sh -c apt-get update -y && apt-get … 20.3MB
f5659402be7a 12 minutes ago /bin/sh -c #(nop) COPY dir:523c1f51e78e02aa1… 335MB
710340b3b82e 2 months ago /bin/sh -c #(nop) CMD ["node"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B
<missing> 2 months ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B
<missing> 2 months ago /bin/sh -c set -ex && for key in 6A010… 5.08MB
<missing> 2 months ago /bin/sh -c #(nop) ENV YARN_VERSION=1.16.0 0B
<missing> 2 months ago /bin/sh -c buildDeps='xz-utils' && ARCH=… 90.4MB
<missing> 2 months ago /bin/sh -c #(nop) ENV NODE_VERSION=12.6.0 0B
<missing> 2 months ago /bin/sh -c groupadd --gid 1000 node && use… 333kB
<missing> 2 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ADD file:5ffb798d64089418e… 55.3MB
パッケージマネージャのキャッシュを削除
これも忘れがちなのですが、パッケージマネージャのキャッシュを削除することで容量減に繋がります
さらに20MB減の490MBになりました
FROM node:12-slim as base
WORKDIR /tmp
RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz \
&& tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz \
&& chown node:node -R /tmp/jdk-12.0.2/
FROM node:12-slim
COPY --from=base /tmp/jdk-12.0.2 /tmp/jdk-12.0.2
RUN apt-get update -y \
&& apt-get upgrade -y \
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
> docker build -t downsize:5 ./
-----------------------------------------------------------------------------------------------------------
REPOSITORY TAG IMAGE ID CREATED SIZE
downsize 5 6de3a6ddead6 About a minute ago 490MB
> docker history downsize:5
-----------------------------------------------------------------------------------------------------------
IMAGE CREATED CREATED BY SIZE
6de3a6ddead6 About a minute ago /bin/sh -c apt-get update -y && apt-get … 3.85MB
f5659402be7a 12 minutes ago /bin/sh -c #(nop) COPY dir:523c1f51e78e02aa1… 335MB
710340b3b82e 2 months ago /bin/sh -c #(nop) CMD ["node"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B
<missing> 2 months ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B
<missing> 2 months ago /bin/sh -c set -ex && for key in 6A010… 5.08MB
<missing> 2 months ago /bin/sh -c #(nop) ENV YARN_VERSION=1.16.0 0B
<missing> 2 months ago /bin/sh -c buildDeps='xz-utils' && ARCH=… 90.4MB
<missing> 2 months ago /bin/sh -c #(nop) ENV NODE_VERSION=12.6.0 0B
<missing> 2 months ago /bin/sh -c groupadd --gid 1000 node && use… 333kB
<missing> 2 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ADD file:5ffb798d64089418e… 55.3MB
スリムなベースイメージを使う
上記のサンプルだとベースイメージにDebian
系を使用していますが、超軽量なAlpine Linux
を使用することで劇的にサイズ減が図れます
ただし下記のnode:12-alpine
はNode.js込みのため、さほどサイズ減につながりませんが、素のAlpine Linuxだと5.53MB !
FROM node:12-alpine as base
WORKDIR /tmp
RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz \
&& tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz \
&& chown node:node -R /tmp/jdk-12.0.2/
FROM node:12-alpine
COPY --from=base /tmp/jdk-12.0.2 /tmp/jdk-12.0.2
RUN apk update \
&& apk upgrade \
&& rm -rf /var/cache/apk/*
> docker build -t downsize:6 ./
-----------------------------------------------------------------------------------------------------------
REPOSITORY TAG IMAGE ID CREATED SIZE
downsize 6 2389f4627226 About a minute ago 415MB
> docker history downsize:5
-----------------------------------------------------------------------------------------------------------
IMAGE CREATED CREATED BY SIZE
2389f4627226 About a minute ago RUN /bin/sh -c apk update && apk upgrade… 22.1kB
<missing> About a minute ago COPY /tmp/jdk-12.0.2 /tmp/jdk-12.0.2 # build… 335MB
<missing> 3 days ago /bin/sh -c #(nop) CMD ["node"] 0B
<missing> 3 days ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B
<missing> 3 days ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B
<missing> 3 days ago /bin/sh -c apk add --no-cache --virtual .bui… 5.5MB
<missing> 3 days ago /bin/sh -c #(nop) ENV YARN_VERSION=1.17.3 0B
<missing> 3 days ago /bin/sh -c addgroup -g 1000 node && addu… 69.3MB
<missing> 3 days ago /bin/sh -c #(nop) ENV NODE_VERSION=12.10.0 0B
<missing> 4 months ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 4 months ago /bin/sh -c #(nop) ADD file:a86aea1f3a7d68f6a… 5.53MB