Dockerfile のマルチステージビルド
Dockerfile のマルチステージビルドを使い、Go アプリケーションの本番環境用の Dockerfile を作る。
リファレンス
本文
Dockerfile のマルチステージビルドを使い、Go アプリケーションの本番環境用の Dockerfile を作る。
前提として Docker Compose を使用する。
まずディレクトリ構成は下記とする。
<root>
|
|-app
| |-go.mod
| |-go.sum
| |-server.go
| |-etc...
|
|-docker
| |-go
| |-Dockerfile.prod
|
|-compose.prod.yaml
app
ディレクトリにソースコードが入っており、app/server.go
がビルド対象である。
docker/go/Dockerfile.prod
が今回作成する本番環境用 Dockerfile。
compose.prod.yaml
が本番環境用 Compose ファイル。
基本的なところはリファレンスを見ればわかるので、私が詰まったところを記載する。
ポイント1. Compose ファイルの build context
compose.prod.yaml
について、build
を以下のようにする。
build:
context: .
dockerfile: docker/go/Dockerfile.prod
今回、docker/go/Dockerfile.prod
には app
ディレクトリ内のファイルを一度コピーするので、context
をルートディレクトリにすることによって Dockerfile.prod
が存在するディレクトリの外にあるファイルも参照可能とする。
ポイント2. Dockerfile でのベースイメージ
完成した Dockerfile.prod
は以下の通り。
FROM golang:1.19 AS build-env
WORKDIR /app
COPY app ./
RUN go mod tidy && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o server server.go
RUN touch /empty
FROM gcr.io/distroless/static-debian11
WORKDIR /app
COPY --from=build-env /app/server ./
COPY --from=build-env /app/.env.prod ./.env
COPY --from=build-env /app/private/prod/*.json ./private/prod/
COPY --from=build-env /empty ./storage/log/.emptyfile
ENTRYPOINT ["./server"]
このファイル内におけるホスト側のファイルパスはルートから見たファイルパスを記載する。
一段階目、COPY app ./
でソースコードを全部コピーできる。
なお COPY app/* ./
とするとローカルパッケージの import に失敗するので注意。
RUN touch /empty
は、二段階目に使うベースイメージで mkdir
を使用できないので /empty
をコピーするという方法でディレクトリを作成するためのもの。
次に二段階目のベースイメージは gcr.io/distroless/static-debian11
を使う。
最初は scratch
を使おうとしたのだが、CA Certificates が入っていないせいで Firebase Authentication が使えなかった。
一から自力で必要なものを入れることのメリットとデメリットを検討し、Google が用意してくれているイメージを使うほうがいいと思ったのでこのベースイメージを使うことにした。
起動
私の Compose ファイルは他のコンテナが .env を使うので、起動はルートディレクトリで
docker compose -f compose.prod.yaml --env-file .env.prod up
となる。
以上