Go製ツールをDockerイメージ化する


背景

Goの強みとして、クロスコンパイルをサポートしており、シングルバイナリにビルドできるので、配布がとても楽というのがあります。
実際、GoxやGoreleaserといったツールはその強みをサポートするべく、様々な環境に向けたクロスコンパイルを設定ファイル等で手軽に駆動させることができます。

ですがそのうえでなお、あらゆる環境がサポートされるわけではないし、すべての環境に向けてクロスコンパイルするのもコスパは悪いし、万能ではありません。

Dockerイメージ化しよう

一つ利用できる環境を増やすアイディアとして、Dockerイメージ化するというのも悪くはないでしょう。
配布したツールを

$ docker run <image-tag>

と呼び出せるようにするわけです。

どうすればいいの

基本的には、Goの入ったDocker内でビルドすればいいんですが、
せっかくですからビルドしたバイナリを単一で別の、より軽量なコンテナに放り込んで動かしたい。

Docker multi stage buildを使えばシンプルです。

FROM golang:alpine AS build-stage
ADD . /work
WORKDIR /work
RUN go build -o entrypoint .

FROM alpine:latest
COPY --from=build-stage /work/entrypoint /usr/local/bin/entrypoint
ENTRYPOINT ["/usr/local/bin/entrypoint"]

他にも、ビルド時に必要なものああればbuild-stageに、実行時に必要な外部リソースがあれば、そちらに、とそれぞれADDすれば問題ありません。

git-vertagという拙作のツールでこの対応をしています。

gitのtagリストからsemantic versionっぽいものを洗い出して、現在の最新バージョンの情報を表示したり、patch / minor / majorのバージョンアップしたタグを打ったりとするツール

GitHub Action上で使いたいという都合があったので、いちいちCI上でGo Buildするのもコストがもったいないので、イメージ化しました。

https://github.com/kyoh86/git-vertag/blob/master/Dockerfile

# Usage:
# docker run -it --rm gcr.io/kyoh86/git-vertag:latest -v ${PWD}:/work patch
FROM golang:alpine AS build-stage
ADD . /work
WORKDIR /work
RUN go build -o git-vertag .

FROM alpine:latest
RUN apk update && apk add git
WORKDIR /work
COPY --from=build-stage /work/git-vertag /usr/local/bin/git-vertag
ENTRYPOINT ["/usr/local/bin/git-vertag"]

このツールは実行時にgitコマンドを使用するため、実行時のイメージ(alpine:latest)の方に apk add git としてgitをインストールしています。