会社の本番環境をAWSのEKSに移行することになりその際にgolangのアプリを配布する際に使用したマルチステージビルドについて備忘録を交えながら記事を書いていきます。
先に言うんですけど
すみません僕Docker自体初めてです
今まで特に自分でDockerなどで環境構築をしたことがなかったのでこれが初めてのDocker作成です。
ほとんど分かっていないのでこいつダメやなって思いながら見てください
マルチステージビルドについて
https://github.com/moby/moby/pull/31257
簡単に言うと、fromでから作られた2つの複数のFROMイメージ間のファイルを COPY --from で直接を参照できるようになったのと AS で中間イメージに名前が付けられるようになったと言うものです。
golangってクロスコンパイルなどでシングルバイナリさえあればgolangの実行環境不要ですもんね
(golangにいては割愛します。)
早速やりましょうか
基本的なファイル構成はこちら
├build(ここにbuildの成果物が格納される)
│ └ appname(実行バイナリ)
├cmd(実行ディレクトリ)
│ └ main.go
├configs(設定ファイル関連)
├bitbucket-pipelines.yml
├.env(環境変数設定ファイル)
├docker-compose.yml
├Dockerfile
├go.mod
├go.sum
├Makefile(タスクランナー実行ファイル)
Makefile
基本的には今回は go build
なども含めて全てMakefile側に任せています。
makefileに関しての設定はここで書きませんがちゃんとbuild配下にバイナリが入るように以下のように設定しました
build:
@go build -ldflags="-w -s" -o build/appname ./cmd/main.go
これでmake build
のコマンドをターミナルで実行するとbuild配下にappnameと言うシングルバイナリが作成されます
Dockerfile
FROM golang:1.12.9 as builder
WORKDIR /appname/
ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64
COPY go.mod .
COPY go.sum .
RUN GO111MODULE=on go mod download
COPY . .
RUN make build
FROM alpine
RUN apk update \
&& apk add --no-cache
COPY --from=builder /appname/build /app/build
ENTRYPOINT [ "/app/build/appname" ]
まずポイントを解説すると
FROM golang:1.12.9 as builder
これでgolangのbaseimageを作成しますこの as builder
と言うのがこの後にこのimageを渡すためのエイリアスになります
ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64
COPY go.mod .
COPY go.sum .
RUN GO111MODULE=on go mod download
COPY . .
go.modはgolangのモジュール関連の設定ファイルです(jsのpackage.jsonみたいなもの)
https://qiita.com/propella/items/e49bccc88f3cc2407745
ENV GO111MODULE=on
はおまじないみたいなもので現行のgo1.13の環境では必要ないと思う(動かなかったらいれてください)
RUN make build
ここでgoのbuildを行います make build
コマンドは先ほど作成した Makefile
のトリガーとして build
を設定していたのでこのようなコマンドでタスクの実行が可能です
クロスコンパイルについてはこちらを参照してください
https://qiita.com/xshirade/items/abeb0d595be27cb6326e
FROM alpine
こちらはDockerの公式が提供している軽量なLinuxのイメージです。
https://alpinelinux.org/
COPY --from=builder /appname/build /app/build
ここで先ほどbuildした実行バイナリの格納ファイル等をこちらにCOPYしています
これでマルチステージビルドの完成です
補足
これでducker build
などでもいいのですが開発環境等でmysqlに接続できる等などの確認が必要だと思うのでdokcer-compose.ymlで環境の構築を行います
version: "3"
services:
mysql:
image: mysql:5.7.26
container_name: db
env_file:
- .env
ports:
- "3306:3306"
volumes:
- db_data:/var/lib/mysql
- ./mysql/scripts/init:/docker-entrypoint-initdb.d
- ./mysql/config:/etc/mysql/conf.d
api:
build: .
depends_on:
- mysql
env_file:
- .env
ports:
- "8080:8080"
volumes:
db_data:
これで
$ docker-compose up --build -d
こちらで接続ができているかなどの確認(go側にmysqlに接続などのプログラムは書いてくださいね)
最後に
僕自身初めてのDockerだったので探り探りでの実装だったのですがもし他にこれの方がいいよってものがありましたら是非教えて頂けますと幸いです。
最後まで読んで頂いてありがとうございました。
次にbitbucket-pipelines.ymlを使用したECRへのPUSHをしたいと思います。