はじめに
Dockerと仲良くなりたいです。
マルチステージビルドとは
複数の処理を 1 つのイメージにすべて詰め込まず、複数の "ビルド用ステージ" を経たうえで、最終的に必要な内容だけをランタイム用イメージに保持する仕組みです。
なぜマルチステージビルドが必要なのか
何かを出力するために複数の処理 a、b、c、d、e があるとします。
インプットは A、最終的に得たい成果物は Z とします。
それぞれの処理には a'、b'、c'、d' といった資材が必要だとします。
これを 1 つのイメージ内で実行しようとすると、必要な内容は以下になります:
A, a', b', c', d', Z
ただしこれではイメージの容量が非常に大きくなってしまいます。
従来の方法(単一ステージ)
FROM ubuntu:22.04 AS base
RUN apt-get update
COPY ./A .
RUN a A
RUN b A
RUN c A
RUN d A
このDockerfileでは、すべての資材(A, a', b', c', d')と成果物(Z)がイメージに含まれてしまいます。
マルチステージビルドの実装
基本的な使い方
しかし、コンテナ実行時に必要なのが Z だけであれば、次のようにステージを分けることができます。
FROM ubuntu:22.04 AS base
RUN apt-get update
COPY ./A .
RUN a A
RUN b A
RUN c A
RUN d A
FROM ubuntu:22.04
COPY --from=base ./Z .
CMD ["./Z"]
こうすることで、前段の base ステージで生成された成果物 Z だけを後段のイメージにコピーし、最終イメージでは Z だけが保持されます。
共通処理を再利用する
また、a、b を共通処理として、c、d、e を追加工程として実施したい場合は次のようにも記述できます。
FROM ubuntu:22.04 AS base
RUN apt-get update
RUN a
RUN b
FROM base
RUN c
RUN d
RUN e
この方法により、baseステージで定義した共通処理を再利用しながら、追加の処理を実行できます。
まとめ
- マルチステージビルドを使うことで、最終イメージのサイズを大幅に削減できます
- ビルドに必要な資材と、実行時に必要な成果物を分離できます
- 共通処理を別ステージに分離することで、Dockerfileの再利用性が向上します
ビルド、という工程の解像度が低いので無理やり整理しましたが、色々やらなきゃいけないことがあるということが感覚的にわかっているならこんな整理はいらないでしょうね。