1️⃣ マルチステージビルドのメリット
-
イメージの軽量化
- ビルド用に必要なツールやライブラリはビルドステージにのみ置き、
実行ステージには最小限のバイナリだけを含める。 - 結果として、イメージサイズが大幅に削減できる。
- ビルド用に必要なツールやライブラリはビルドステージにのみ置き、
-
ビルド時間短縮
- 不要な依存やレイヤを実行ステージに含めないことで、
ダウンロードや展開の時間を削減。
- 不要な依存やレイヤを実行ステージに含めないことで、
-
セキュリティ向上
- 実行用ステージにコンパイルツールを含めないため、攻撃対象を減らせる。
-
保守性・可読性向上
- 「ビルド」「実行」をステージごとに分けることで、Dockerfileが整理され、
更新やデバッグがしやすくなる。
- 「ビルド」「実行」をステージごとに分けることで、Dockerfileが整理され、
2️⃣ 改善前サンプルコード(単一ステージ)
# golangイメージをベースに使用
FROM golang:1.13.4-alpine3.10
# 作業ディレクトリを/srcに設定
WORKDIR /src
# Goアプリケーションのソースをコンテナにコピー
COPY ./main.go /src
# Goでバイナリをビルドし、実行可能ファイルを/usr/local/bin/startappに出力
RUN go build -o /usr/local/bin/startapp main.go
# 作業ディレクトリをルートに戻す(任意)
WORKDIR /
# コンテナ起動時に実行するコマンドを指定
CMD ["/usr/local/bin/startapp"]
3️⃣ 改善後サンプルコード(マルチステージ)
# ===== ビルドステージ =====
# golangイメージを使用してビルド専用ステージを作成
FROM golang:1.13.4-alpine3.10 AS builder
# 作業ディレクトリを/srcに設定
WORKDIR /src
# ソースコードをコピー
COPY ./main.go /src
# Goでバイナリをビルド
# CGO_ENABLED=0: CGOを無効化(完全な静的リンク)
# GOOS=linux GOARCH=amd64: Linux x86_64向けにビルド
# -a -installsuffix cgo: 全て再ビルド
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -a -installsuffix cgo -o startapp main.go
# ===== 実行ステージ =====
# 最小限のベース(scratch)を使用
FROM scratch
# ビルドステージからバイナリだけをコピー
COPY --from=builder /src/startapp /startapp
# コンテナ起動時に実行するコマンドを指定
CMD ["/startapp"]
4️⃣ main.go(共通)
package main
import (
"net/http"
"fmt"
)
func main() {
// "/" にアクセスがあった場合のハンドラ関数
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello go") // レスポンスに "hello go" を返す
})
// ポート80でHTTPサーバを起動
http.ListenAndServe(":80", nil)
}
5️⃣ 改善結果の定量比較
| 項目 | 改善前 | 改善後 | 改善率 |
|---|---|---|---|
| ビルド時間 | 約900秒(約15分) | 約180秒(約3分) | 約 1/5 に短縮 |
| イメージサイズ | 約700MB | 約22MB | 約 1/30 に軽量化 |
6️⃣ 実行手順
# イメージビルド
docker image build -t c4app5 .
# イメージサイズ確認
docker image ls c4app5
# REPOSITORY TAG IMAGE ID CREATED SIZE
# c4app5 latest abc123... X minutes ago 22MB
# コンテナ実行
docker run -d -p 8080:80 c4app5
# 動作確認
curl http://localhost:8080
# => hello go
7️⃣ まとめ
- 単一ステージではビルド環境の依存がそのまま残るためイメージが重い
- マルチステージ化により、不要な依存を除去して軽量・高速なイメージ作成が可能
- Scratchベースで最小限バイナリだけを配布
- Dockerfile構造を整理することで保守性・可読性が向上
出典
伊藤裕一著『たった1日で基本が身に付く Docker/Kubernetes超入門』技術評論社
P128~P136 chapter4 session2 Docker向けの小さいイメージを作成してみよう