dockerのマルチステージビルドとホットリロード環境@Golang
dockerのマルチステージビルドとは
dockerにはマルチステージビルドというイメージ容量を簡単に小さくできる構文が用意されている。
マルチステージビルドでは、Dockerfileの中で複数のFROM
文を使用し、各FROM
では異なるベースイメージを用いて新しいステージを構築できる。任意のステージから別のステージにコピーする対象を選べるので、最終的なイメージでは必要なものだけでビルドされる。
With multi-stage builds, you use multiple FROM statements in your Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image.
必要なファイルのみをビルドすることができるため、軽量なAlpine-Linuxなどをベースイメージとしてバイナリファイルだけをコピーすることでイメージサイズを小さくすることができる、という具合。
Airによるホットリロード環境
dockerで開発を進める際に、ローカルのソースコードに変更があるたびにコンテナに反映する必要がある。変更毎にコンテナを再起動するのは面倒だ。Airを使うことでローカルの変更をコンテナを再起動せず、コンテナへの即時反映が可能になる。詳細は以下を確認。
上記を踏まえて、以下の要件を満たすGolangの環境構築を行いたい。
- dockerのマルチステージビルド
- Airを用いたホットリロード
実装
最終的なディレクトリ構成は以下。簡単にwebサーバーを立て、レスポンスを返す実装のみしている。
.
├── Dockerfile
├── docker-compose.yml
├── go.mod
└── main.go
version: "3"
services:
go-env:
container_name: go-env
build:
args:
- target=dev # デフォルトはローカル用ホットリロード環境
volumes:
- .:/app
ports:
- "9090:8080"
# Build Stage for deploy --------------------
FROM golang:1.18-alpine AS deploy-builder
WORKDIR /app
COPY go.mod ./ # 必要があればgo.sumもコピーする
RUN go mod download
COPY . .
RUN go build -ldflags "-w -s" -o main
# Deploy Stage ------------------------------
FROM alpine:latest AS deploy
RUN apk update
COPY --from=deploy-builder /app/main . # プログラム実行に必要なバイナリファイルのみコピー
CMD ["./main"]
# Local -------------------------------------
FROM golang:1.18 AS devlop
WORKDIR /app
RUN go install github.com/cosmtrek/air@latest
CMD ["air", "-c", ".air.toml"]
# 他はほぼデフォルト
[build]
full_bin = "APP_ENV=dev APP_USER=air ./tmp/main 8080" # コンテナ側ポート
デプロイ用のコンテナとローカル開発用コンテナの出しわけは、docker build
で--target
オプションで出しわけをすることができる。今回はローカル開発環境がデフォルトでビルドされるようにdocker-compose.yml
に記述している。
ローカルの環境構築するときの手順は以下で行なった。
# ビルド(ローカルは--targetを指定しないでok)
$ docker compose build --no-cache
# .air.tomlファイルの生成("go-env"は各自docker-compose.ymlで設定したサービス名に変換のこと)
$ docker compose run go-env --rm air init
# コンテナ起動
# docker compose up -d
デプロイ環境のビルドはこんな感じ。
$ docker build -t awonosuke/go-env:latest --target deploy ./
一応、GitHubに残しておいた。
検証
用意したホットリロードがうまくいっているか、デプロイ用のコンテナはどの程度軽量になっているのかをせっかくなので検証したい。
Under construction...
おまけ
ホットリロードとは?
アプリケーションのコード ファイルを編集し、そのコード変更を実行中のアプリケーションに対して直ちに適用できるようにすることで、これを実現します ("ホット リロード" とも呼ばれます)。
参考書籍
参考ページ
Discussion