はじめに
Dockerでイメージをビルドする際は、なるべくイメージサイズを小さく抑えることが推奨されています。
イメージサイズを小さく抑えることのメリットは以下の通りです。
- デプロイが高速になる。
- アプリケーションの起動が早くなる。
- スケーラビリティが向上する。
イメージが軽量であればビルド時間やダウンロード時間が短縮され、デプロイを高速に完了することができます。また、軽量化によりアプリケーション起動の高速化も期待できます。
スケーラビリティの観点では使用するリソースを抑えることで、少ないリソースで多数のコンテナを実行できる可能性があります。
イメージの軽量化/高速化
それでは以下のDockerfileを参考に軽量化の方法について確認していきます。
FROM golang:1.18-alpine AS build-env
WORKDIR /app
COPY go.mod .
COPY go.sum .
# --no-cacheを付けることで/var/cache/apk/配下にメタデータをキャッシュしない
RUN apk add --no-cache upx
RUN go version
RUN go mod download
COPY . .
# CGO_ENABLED=0: C言語のライブラリは使用しないためCGOを無効化して依存関係をなくす
# -buildvcs=false: vcsのバージョン情報をバイナリに含めない
# -trimpath: ビルド環境のローカルパス情報を取り除く
# -ldflags '-w -s': リンカーへのフラグで、-w はデバッグ情報を生成しない、-s はシンボルテーブルを削除する効果がある
RUN CGO_ENABLED=0 go build -buildvcs=false -trimpath -ldflags '-w -s' -o /go/bin/app
RUN upx /go/bin/app
FROM scratch
COPY --from=build-env /go/bin/app /go/bin/app
ENTRYPOINT ["/go/bin/app"]
軽量化
マルチステージビルド
マルチステージビルドを使用することで、ビルドの環境を複数に分け、最終的な成果物であるイメージにはアプリケーションの実行ファイルのみを含めるようにしています。
上記のDockerfileではbuild-env
の環境でGo言語のプログラムのビルドを行い、scratchのベースイメージで作成した環境(最終的な成果物となるイメージ)にはビルドされた実行ファイルのみをコピーしています。
これによって最終的に出来上がるイメージにはscratchイメージ(何もインストールされていない空っぽの軽量なイメージ)にアプリケーションの実行ファイルだけを乗せた、軽量なイメージを作成することができます。
UPX
もう一点特筆すべき点として、ビルド後の実行ファイルをUPXコマンドで圧縮して小さくしています。
実際のアプリケーションによりますが、簡単なAPIサーバーのアプリケーションでは、4.83MBだったものが、UPXを使うことにより2.01MBまで小さくすることができました。
これ一つで大きな違いが出ますので積極的に使用していきたいですね。
ビルド高速化の観点
上に書いたものはイメージのサイズを小さくする上でのポイントですが、ビルドを高速化する上でも色々な工夫の方法があります。
上記のDockerfileでもコメントを入れている箇所で不要なものを極力排除するフラグを設定しています。
ぜひ参考にしてみてください。
終わりに
いかがでしたでしょうか。
プロダクション環境で使用するイメージを構築する際には色々な観点でビルド高速化やイメージの軽量化で効率化されていることが多いものです。
本記事がGoのアプリケーションをビルドする際の参考になれば幸いです。