【Docker】Docker ~ マルチステージビルド ~

◾️はじめに

https://dk521123.hatenablog.com/entry/2025/01/20/001754

で紹介した「つくって、壊して、直して学ぶ Kubernetes入門」を
買って、全然読んでなかったので、GW中に読んでみようと
思ったペラペラめくってたら「マルチステージビルド」ってのが
出てきたので、まとめてみる

目次

【0】前提知識
【1】マルチステージビルド (Multi-stage builds)
【2】マルチステージビルドの利点
 1)最終イメージサイズ削減
 2)セキュリティ向上
 3)Dockerfile可読性向上
【3】サンプル
 1)Go

【0】前提知識

当たり前かもしれないが、、、

* コンテナは、なるべく軽い方が起動・更新が早くなるため、
 良いとされている
* 脆弱性を減らすために、ライブラリ群も少ない方がいい

【1】マルチステージビルド (Multi-stage builds)

 1つのDockerfile内で
「ビルド用の環境(重い)」と「実行用の環境(軽い)」
に分けて作成することにより、
最終イメージには「実行に必要な成果物のみ」を入れる仕組む

【2】マルチステージビルドの利点

* 以下、利点

1)最終イメージサイズ削減
2)セキュリティ向上
3)Dockerfile可読性向上

1)最終イメージサイズ削減

* ビルド用の環境が含まれないため、
 最終イメージサイズが削減される

2)セキュリティ向上

* ビルド用の環境でしか使わないツール群は
 最終イメージには含まれないため、脆弱性での攻撃が減らせる

3)Dockerfile可読性向上

* Dockerfileで1枚で完結できる

【3】サンプル

1)Go

.
├── dockerfile
└── main.go
---
├── go.mod ... ビルド後にできる

dockerfile

# 1) build stage
# Point1: FROM xxx AS build のようにステージに名前をつける
FROM golang:1.23-alpine AS build
WORKDIR /app
COPY . .
ENV CGO_ENABLED=0
RUN go build -o hello .

# 2) final stage
FROM scratch
COPY --from=build /app/hello /hello
CMD [ "/hello" ]

dockerfile

package main

import (
  "fmt"
  "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintln(w, "Hello world!!")
}

func main() {
  http.HandleFunc("/", handler)
  http.ListenAndServe(":18080", nil)
}

コマンド

 docker build . --tag hello-server:1.0

 docker images hello-server

docker run --rm --detach --publish 18081:18080 --name hello-server hello-server:1.0

curl localhost:18081
# Hello world!!

docker stop hello-server

関連記事

Docker ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2020/04/24/160044
Docker ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2023/02/25/000000
Docker ~ 基本編 / Dockerfile ~
https://dk521123.hatenablog.com/entry/2020/04/14/000000