Docker の multi-stage builds 試してみた
multi-stage buildsとは
まずはドキュメントから。
Use multi-stage builds | Docker Documentation
multi-stage buildsとは、アプリケーションのビルド環境と実行環境を分けることが出来る機能 っぽいです。
これは最高ですね。
今開発しているElixirアプリケーションのDockerfileでは、Elixirのビルド環境で使用したソースや、依存ライブラリを最後に削除しております。
こういう使い方してるところ多いんじゃないかなと思いますが、すべてはコンテナイメージを軽量化するためですね、以下例。
FROM elixir:1.6-alpine -- 省略 -- # Install RUN apk update && \ apk upgrade && \ apk add bash && \ apk --no-cache add imagemagick && \ apk --no-cache add --virtual build-dependencies build-base musl-dev && \ mix local.hex --force && \ mix local.rebar --force -- 省略 -- # Delete RUN apk del --purge build-dependencies && \ rm -f opt/app/.mix && \ cp ${TARBALL} ${APP}.tar.gz && \ ls | grep -v ${APP}.tar.gz | xargs rm -r && \ tar xfz ${APP}.tar.gz && \ rm -f ${APP}.tar.gz
Golangで試す
前回Golangで作ったmp4連結アプリのDockerfileをmulti-stage builds で書いてみます。
FROM golang:latest as builder WORKDIR /go/src/github.com/yuki-toida/video-concater/ COPY . . RUN go get -u github.com/golang/dep/cmd/dep && \ dep ensure -v && \ CGO_ENABLED=0 GOOS=linux ENV=dev go build -o app . FROM alpine:latest EXPOSE 8080 ENV ENV=dev \ GOOGLE_APPLICATION_CREDENTIALS="./cred/gcs.json" RUN apk update && \ apk upgrade && \ apk add --no-cache ca-certificates && \ apk add --no-cache ffmpeg WORKDIR /opt/app COPY --from=builder /go/src/github.com/yuki-toida/video-concater/app . COPY --from=builder /go/src/github.com/yuki-toida/video-concater/index.html . COPY --from=builder /go/src/github.com/yuki-toida/video-concater/config ./config COPY --from=builder /go/src/github.com/yuki-toida/video-concater/cred ./cred CMD ["./app"]
いいですね。
最初のfrom
がビルド環境、次のfrom
が実行環境。
見ての通りビルド環境のイメージはgolang:latest
で、実行環境のイメージはalpine:latest
になってます。
実行環境ではビルド環境でビルドされた実行ファイルをCOPY
してるだけのシンプルな構成です。
まとめ
おそらく今後は基本 multi-stage builds 使うんじゃないかなというくらい良いですね。
ビルドとランタイムでは担っている責務が大きく違うので、見通しがよいmulti-stage builds
を使うのが自然ですね。