Go で Docker の multi-stage build を試す


前提

  • Docker がインストールされていること

手順

Go ファイルを作成

app.go という名前のファイルを作成する。

app.go に「Hello, world」と出力するだけのコードを書く。
(ホストOS に Go がインストールされてなくても

app.go
package main

import "fmt"

func main() {
    fmt.Println("Hello, world")
}

Dockerfile を作成

Go ファイルと同じディレクトリに Dockerfile を作成する。
「Go のバイナリをビルドする環境」と「Go のバイナリを実行する環境」の定義を記述する。

Dockerfile
# 「builder」という名前で Dockerfile 内から参照できるようにする
FROM golang:1.13 AS builder
WORKDIR /root
# 作成した Go ファイルをコピー
COPY . /root
# Linux 用のバイナリをビルドし、WORKDIR に出力
RUN GOOS=linux go build -o app .

# scratch は超軽量なイメージ
FROM scratch
WORKDIR /root
# 「builder」にあるバイナリを WORKDIR にコピー
COPY --from=builder /root/app .
CMD ["./app"]

イメージをビルド & コンテナ起動

Go ファイルと Dockerfile があるディレクトリでターミナルを起動し、イメージをビルド & コンテナ起動する。

terminal
# app という名前でイメージをビルド
docker build -t app .

# app のコンテナを起動( --rm はコンテナ停止時にコンテナを削除するオプション )
docker run --rm app
# app.go の実行結果が出力される
> Hello, world

# app のイメージサイズ ≒ バイナリのサイズ で「Go のバイナリを実行する環境」が実現できたことがわかる
docker images app --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
REPOSITORY          TAG                 SIZE
app                 latest              2.01MB