0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Dockerfileのリファクタをしてみる[Go]

Posted at

Dockerfile、いつも脳死で書いている方なので、今回少しでも改良しつつ色々学べないかなと思い、色々直してみました。

既存のDockerfile

既存のDockerfileは下のようになっていました。

FROM golang:1.24.4-bookworm
WORKDIR /go/src/app
COPY . .
RUN go mod download
RUN CGO_ENABLED=0 go build -v -o binary main.go
EXPOSE 3000
CMD ["./binary"]

このDockerfileのあまり良くないかなと思うところは全ファイルをコピーしているため、動作には必要ないツールの設定ファイル等の余分なファイルが含まれてしまい、イメージが大きくなってしまっています。

イメージが大きいと

  • build時間の増加
  • ecr等へのpush時間の増加
  • ローカルストーレージの圧迫

といったデメリットがあります。
実際にイメージサイズは1.48GBとなっていました。

また、go mod downloadを行なっているため、毎回イメージ作成時にダウンロードを行なってしまっています。
そのためビルド時間は49sとかなり長いです。

[+] Building 49.8s (12/12) FINISHED

直してみる

上記の点を踏まえてDockerfileを改良してみました。

FROM golang:1.24.4-bookworm
ENV APP_DIR=/go/src/app
COPY go.mod go.sum $APP_DIR/
COPY vendor/ $APP_DIR/vendor/
COPY main.go $APP_DIR/
COPY common $APP_DIR/common/
COPY application/ $APP_DIR/application/
COPY domain/ $APP_DIR/domain/
COPY infrastructure/ $APP_DIR/infrastructure/
COPY interfaces/ $APP_DIR/interfaces/
COPY migrations/ $APP_DIR/migrations/
COPY .env $APP_DIR/
WORKDIR $APP_DIR
RUN CGO_ENABLED=0 go build -mod=vendor -v -o binary main.go
EXPOSE 3000
CMD ["./binary"]

まず、全ファイルコピーをせず、動作に必要なファイルだけコピーするようにしました。
こうすることによって必要なファイルだけを取り入れるようになり、イメージサイズも1.18GBと300MBほど小さくなりました。

また、vendorディレクトリをコピーするようになったのでその分ビルド時間が短縮されました。
結果30sほど短くなりました。

[+] Building 16.5s (19/19) FINISHED

マルチステージングビルドを行ってみる

これでもイメージサイズがまだ大きいなと感じたのでマルチステージングビルドを行ってみます。

マルチステージングビルドとは

Dockerfileの読みやすさやメンテナンスのしやすさを維持するために、段階的にイメージのビルドが行える仕組みのことです。

以下のように書いてみました。

FROM golang:1.24.4-bookworm AS builder
ENV APP_DIR=/go/src/app
COPY go.mod go.sum $APP_DIR/
COPY vendor/ $APP_DIR/vendor/
COPY main.go $APP_DIR/
COPY common $APP_DIR/common/
COPY application/ $APP_DIR/application/
COPY domain/ $APP_DIR/domain/
COPY infrastructure/ $APP_DIR/infrastructure/
COPY interfaces/ $APP_DIR/interfaces/
WORKDIR $APP_DIR
RUN CGO_ENABLED=0 go build -mod=vendor -v -o binary main.go

FROM gcr.io/distroless/base
WORKDIR /app
COPY --from=builder /go/src/app/binary ./
EXPOSE 3000
ENTRYPOINT ["./binary"]

下の方に数行だけ追加されていると思うのですが、これが2段階目のビルドです。
こちらではdistrolessというイメージを使って、そこにバイナリファイルだけ移動させるということを行なっています。

distrolessとは

Googleが提供している必要最小限の依存のみが含まれるコンテナイメージで、Debian10を基に作成されたものだそうです。
aptやshellも含まれておらず、非常にサイズの小さいイメージになっています。

これを行うことでイメージサイズがなんと58.20MBになりました。

ビルド時間も16.5sとあまり変わらない結果になったので、マルチステージングビルドがなぜよく使われているのか知れた気がします。

まとめ

今回、Dockerfileの改良のために

  • COPYするファイルを限定化
  • goのモジュールをvendorに移行
  • マルチステージングビルドの採用

を行なってみました。

これ以外にも良くするコツがあると思うので、また知ったら記事にしようかなと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?