at kaneshin

Free space for me.

Cloud Buildを使ってコンテナを自動ビルドする

この記事は Docker Advent Calendar 2018 6日目の記事です。

はじめに

エウレカでは開発したBotやアプリケーションについて、Dockerコンテナ化がなされていれば、会社が用意した環境にデプロイするような仕組みを整えています。

medium.com

本日は、初学者向けに、Go+Docker+GCP+Terraformを使ったコンテナ作成について紹介をします。

事前準備

とりあえず、Dockerだけインストールしておいてください。

あと、2年前にも似ている記事を書いているので、そこも参照すると良いかもしれません。

blog.kaneshin.co

※古いので、そこだけはご了承を

Go without Go

普段、サーバーで開発をしているため、ローカルではほとんど開発を行っていません。環境構築が必要になったときは必ずDockerコンテナを利用しています。それに合わせて、今回はDockerをメインに開発を行います。また、サンプルリポジトリとして3年前に作ったbase64のアプリケーションサーバーを用います。

github.com

これを、ひとまずローカル環境で動かします。私はMacを使うことが多いのでMacにクロスコンパイルしたバイナリを作成します。

# ホストとマウントさせて、go getを行う(必要があれば編集をローカルで行うため)
$ docker run -v ~/go:/go golang go get -v github.com/kaneshin/base64server

# ホストにあるコードをdockerコンテナ経由でビルドします
$ docker run -v ~/go:/go -e GOOS=darwin -e GOARCH=amd64 golang go install github.com/kaneshin/base64server

# クロスコンパイルしたバイナリを起動します
$ ~/go/bin/darwin_amd64/base64server 

# 別のセッションでアプリケーションにリクエストを送り、テキストをエンコードします
$ curl 'localhost:8080/encode?v=hoge'
aG9nZQ==

docker run golang

docker run golang を行うことで、docker-library/golangに管理されているDockerコンテナを取得し、実行します。

github.com

各Dockerfileを読めば、どのような情報でコンテナが用意されているかがひと目でわかるので、確認が必要ならば目視チェックします。

ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH

RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
WORKDIR $GOPATH

golangのコンテナでは、 $GOPATH/go が設定されているため、基本的にはここをマウントポイントとしています。

Dockerfileの準備とコンテナの実行

さて、先ほどはローカル環境にバイナリを作成して起動をしました。これだけだと、Goの環境を整備せずにコンテナを使っただけに過ぎません。では、次に、このアプリケーションをコンテナ化してしまいます。

FROM golang:1.11.2

RUN mkdir -p /go/src/github.com/kaneshin/base64server
ADD . /go/src/github.com/kaneshin/base64server/

RUN go build -o main github.com/kaneshin/base64server

EXPOSE 8080
CMD ["./main"]

ADD . /go/src だけでも構わないのですが、本家に合わせていくスタイルや規模の大きいプロジェクトなどを考慮すればこのようにした方がラクです。

$ cd ~/go/src/github.com/kaneshin/base64server

# Dockerfileを元にビルド
$ docker build -t base64server .

# ビルドしたコンテナを起動
$ docker run -p 8080:8080 base64server

# 別のセッションでアプリケーションにリクエストを送り、テキストをエンコードします
$ curl 'localhost:8080/encode?v=hoge'
aG9nZQ==

ここまではコンテナに慣れている人は簡単ですね。

GCPと連携する

Cloud Source Repositories

Cloud Source Repositories を開き、ポチポチとGitHubのリポジトリと連携します。

f:id:laplus-knsn:20181206211635p:plain

連携が完了すると、github_kaneshin_base64server のようなリポジトリ名でリポジトリが作成されています。

Cloud Buildと連携する

ここからは、gcloudgsutil が必要になるので、ここもDockerでどうにかします。

# cloud-sdkのDockerコンテナをpullしてくる
docker run -ti google/cloud-sdk gcloud version

# GCPに認証を通す
docker run -ti --name gcloud-config google/cloud-sdk gcloud auth login

# VolumeからCredentialsを引き継ぎしつつ、gsutilでTerraform state用のバケットを作成
docker run --rm -ti --volumes-from gcloud-config google/cloud-sdk gsutil mb -p [YOUR-PROJECT-ID] -c multi_regional -l Asia gs://terraform-state

Terraformで環境構築

ここはDockerじゃなくて実際のTerraform使います。

$ cd ~/go/src/github.com/kaneshin/base64server/terrafrom

# 必要なプラグインを入れるおまじない
$ terraform init

# Placeholderになっている変数を適切に注入
$ terraform plan -var 'project_id=[YOUR-PROJECT-ID]' -var 'credentials_file_path=[YOUR-CREDENTIALS]' -var 'env=prod'
$ terraform apply -var 'project_id=[YOUR-PROJECT-ID]' -var 'credentials_file_path=[YOUR-CREDENTIALS]' -var 'env=prod'

下記のように、Cloud Build上でトリガーが設定されます。

f:id:laplus-knsn:20181206221059p:plain

そして、トリガーが発火されると、Container Registryにコンテナが作成されます。

f:id:laplus-knsn:20181206221123p:plain

おわりに

3, 4年前からDockerは触っていますが、周辺環境もキレイに整ってきていて昔と比べて本当に使いやすくなったの一言ですね。Dockerは入りが難しいと思われがちですが、パターンさえ覚えてしまえば下手な環境構築よりかも簡単です。