GoのプロジェクトをDockerで動かすことがあると思う.
知らんけど.
まぁきっとあるんだろう.
ちなみに私は何度かある.
私がよく使うDockerfileの設定を書いておく.
Dockerのimageをbuildするときに気を使うことが一つだけある.
それはimageのサイズを小さくすることである.
何も考えずにGoのプロジェクトをbuildすると多分こんな具合だろう.
FROM golang:latest
WORKDIR /go/src/hogehoge.com/who/bar
COPY . .
RUN set -e \
&& go build -o /bin/bar main.go
WORKDIR /
RUN set -e \
&& rm -rf /go/src
CMD ["bar"]
流石にここまで雑に書くことはなかなか無いだろうが, 一応ビルドして掃除までしている.
だが小さくするには不十分である.
まずGoのDocker imageがそれなりに大きい.
2018-12-12のlatestの段階で774MBある.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
golang latest df6ac9d1bf64 3 weeks ago 774MB
Goはシングルバイナリのビルド物を生成する.
なので実行時にコンパイラは必要ない.
GoのbaseになってるDocker imageはDebianである.
なのでGoのdocker imageでバイナリを生成してDebianのimageにうつしてやればいいじゃんてなるだろう.
Debianのlatestのimageは101MBである.
小さいように見えるがまだダイエットが可能である.
alpine Linuxというもっと小さいDocker imageが用意されている.
alpine Linuxのlatestのサイズは4.41MBである.
たぶんGoの実行バイナリより小さい.
Goのimageでgoのソースコードをコンパイルして作られたバイナリをalpine linuxのimageに入れてやれば良い.
このとき気おつけないといけない事がある.
Goのimageはlibcに使われてるのがglibcである.
しかしalpine linuxにはglibcが入っていない.
なのでGoをコンパイルするときstatic link化してやる必要がある.
そこらへんは先人の方が解説してくれているので参考にみてほしい.
なのでDocker fileに起こすと次のようにかける.
FROM golang:latest AS build
WORKDIR /go/src/hogehoge.com/who/bar
COPY . .
RUN set -e \
&& go build -o /tmp/bar main.go
FROM alpine:latest
COPY --from=build /tmp/bar /bin/bar
CMD ["bar"]
こうかくとalpine linuxのimageサイズとgoのバイナリのサイズを足した容量でDocker imageを構築できる.
あとDocker imageの掃除にそこまで気を使わなくて良くなる.