の続き。
概要
今回作成したサービスがopencvなどの環境を作成するのが面倒で、buildするのも一苦労するため、buildについてもdockerの中でやってしまおう、ということで試してみた。
topic
- opencvやgstreamerなど多くのライブラリが必要
- 開発環境用docker imageがそのまま使用できそう
- goライブラリの中に、privateなライブラリが含まれている
- 上記にアクセスするために、SSH鍵が必要
- 前段のgo build処理 、通常のdocker buildのマルチステージビルド
Dockerfile
今回作成したDockerfileは以下。
ベースイメージであるghcr.io/my_organization/devcontainer-go1.15-opencv4.5:latest
については、
を参照。(上記からの連続記事です)
# syntax=docker/dockerfile:1.0.0-experimental
FROM ghcr.io/my_organization/devcontainer-go1.15-opencv4.5:latest as go-build
# set Hoge lib as private
ARG GOPRIVATE=github.com/Hoge
# for gocv
ARG LD_LIBRARY_PATH=/usr/local/lib:/app/lib
# for Hoge
ARG CGO_LDFLAGS="-L/app/lib -lHoge"
# for gocv
ARG PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/local/lib/pkgconfig
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
# ソースコードを/appにコピー
COPY . /app
WORKDIR /app
RUN git config --global url."ssh://git@github".insteadOf https://github
RUN --mount=type=ssh go mod tidy
RUN go build -o main ./cmd
FROM ghcr.io/my_organization/devcontainer-go1.15-opencv4.5:latest
RUN mkdir /app
WORKDIR /app
# 1つ目のステージからバイナリだけコピー
COPY --from=go-build /app/main ./main
CMD ["./main"]
syntax=docker/dockerfile:1.0.0-experimental
go mod tidy
するためにホスト側のssh private keyをコンテナ内で使用する必要があった。DockerのBuildKitを使うとコンテナに含まれないようにsecret情報をbuild中にマウントできるという情報があり、使ってみた。
その機能を使うためにDockerfileの先頭にこの一行が必要。
参考
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
known_hostsを作成するおまじない。goライブラリをダウンロードするときにgithub.comが追加されている必要があるため。
RUN git config --global url."ssh://git@github".insteadOf https://github
golangのプライベートライブラリにsshでアクセスするためのおまじない。
RUN --mount=type=ssh go mod tidy
今回の肝。これでローカルホスト側のssh鍵をマウントしている。実際にマウントされる鍵は、docker build実行時に指定する。
Makefile
IMAGE=ghcr.io/my_organization/my_application
TAG=latest
build:
docker build --ssh default=${HOME}/.ssh/id_rsa -t $(IMAGE) .
docker tag $(IMAGE) $(IMAGE):$(TAG)
docker push $(IMAGE):$(TAG)
これで
$ make build
でgo build、docker buildが行われてrepositoryにpushされる。
評価
ssh鍵をdockerコンテナ内で使う方法で悩んだ。BuildKitを使う事で上記はクリアし、シンプルなDockerfile & Makefileになったように思う。
開発環境をそのままビルド環境に利用したことの是非は判断できていない。
開発環境イメージには不要なものもたくさん含まれているとは思うものの、開発環境なら確実にビルドできるだろう、という思いもある。
ビルドに不要なものを.dockerignoreで外すのをお忘れなく!