🐳

最新手法で学ぶDockerfile:マルチステージビルドとGoを活用した最適化

2024/10/08に公開

はじめに

本記事では、シンプルなGoプログラムをDockerを使って効率的にビルドおよび実行する方法を解説します。Dockerfileを利用し、以下の最新の手法を適用することで、コンテナイメージの最適化と実行環境の軽量化を実現します。

  • キャッシュを利用してビルド速度を向上させる
  • マルチステージビルドで依存関係とビルドを分離
  • レイヤーの最小化によるイメージサイズの削減
  • 軽量なDebianベースのイメージの利用

プログラムの概説

今回扱うGoプログラムは、非常にシンプルな「Hello World」を表示するものです。main.goは以下のような内容となっています。

package main

import "fmt"

func main() {
	fmt.Println("Hello World !")
}

このプログラムは、コンソールに「Hello World !」と出力するだけの非常に基本的なものです。このプログラムをDockerを使ってビルドおよび実行する際に、効率を最大限に引き出すため、最新のDockerfile設計を採用します。

最新の手法を用いた Dockerfile

# ビルドステージ - Golang環境を使用してビルド
FROM golang:1.23.2 AS builder

# 作業ディレクトリの設定
WORKDIR /app

# キャッシュを効率的に使うためにgo.modとgo.sumを先にコピー
COPY go.* ./
RUN go mod download

# ソースコードをコピー
COPY . .

# Makefileを使ってビルド
RUN make build

# 実行ステージ - 軽量なDebianベースのイメージ
FROM gcr.io/distroless/base-debian10

# ビルドされたバイナリをコピー
COPY --from=builder /app/main /usr/local/bin/main

# アプリケーションを実行
CMD ["main"]

キャッシュを利用する

Dockerのキャッシュ機能を活用することで、ビルドのパフォーマンスを大幅に向上させることができます。キャッシュを有効にするために、依存関係のダウンロードやビルドプロセスを適切な順番で記述することが重要です。go.modgo.sumを先にコピーし、それから依存関係をダウンロードすることで、ソースコードが変更されない限りこのステップがキャッシュされます。

マルチステージビルドの利用

マルチステージビルドを使用すると、ビルド環境と実行環境を分離できるため、ビルドに必要なツールを最終的なイメージに含めないようにすることができます。これにより、実行環境が軽量化され、コンテナイメージのサイズが小さくなります。

レイヤーの最小化

レイヤーを最小化することは、コンテナイメージのサイズ削減につながります。Dockerfile内でできる限り1つの命令にまとめることで、レイヤーを減らし、不要なファイルがイメージに残らないようにします。

Debianベースのイメージの利用

最終的な実行環境には軽量なDebianベースのイメージ(gcr.io/distroless/base-debian10)を使用します。最小限のパッケージしか含まれておらず、サイズが小さいため、効率的なGoアプリケーションの実行に適しています。

Makefile について

Dockerfileの中で使用するmake buildコマンドは、Makefileで定義されています。このMakefileにより、Goプログラムのビルドが管理され、ビルド・実行・クリーンなどの操作が簡単に行えるようになります。以下がそのMakefileです。

.PHONY: build run clean

build:
	go build -o main main.go

run:
	./main

clean:
	rm -f main

まとめ

今回の記事では、GoプログラムをDockerfileとMakefileを組み合わせて効率的にビルド・実行するために、以下の最新手法を取り入れました。

  • キャッシュの利用: 依存関係のダウンロードをキャッシュすることで、ビルド時間を短縮します。
  • マルチステージビルド: ビルド環境と実行環境を分けることで、軽量な実行イメージを作成します。
  • レイヤーの最小化: Dockerfileの命令を最適化し、イメージの無駄を削減します。
  • Debianベースのイメージ: 軽量かつ信頼性の高いDebianベースのイメージを使用しました。

さらに、Makefileを使用することで、ビルドや実行のプロセスを簡単に管理できるようにしています。

Discussion