目次
前回 Cloud BuildでGAE/Goデプロイ by Slack vol.3
Cloud BuildでGAE/Goのデプロイ
Cloud BuildでGAE/Goデプロイ by Slack vol.4ということで、
今回はCloud BuildでGAE/Goをデプロイする設定を行います。
といっても、
ここまでの設定ができていれば、
デプロイ自体はgcloudコマンドを使えば、コマンド一発で済むので難しいことはありません。
では、早速やってみましょう。
GAE/Goのソース
今回デプロイするコードは、
にあります。
コードの詳細は割愛しますが、
アクセスすると、”Shaken, not stirred. “というメッセージを表示するHTMLを返すだけのものです。
無駄にGo言語のフレームワークであるMartiniを使ってますが、
これは、単純に上記メッセージから連想したってのもありますが、
GAEに外部ライブラリを使う上で注意する点があったので、
その説明のために、追加しました。
(後述します。)
[speech_bubble type=”std” subtype=”L1″ icon=”neko_07-1.png” name=””]マティーニで、”Shaken, not stirred.”とくれば、あの男しかいないにゃ[/speech_bubble]
さて、デプロイするためのcloudbuild.ymlの記述ですが、
steps: - name: 'gcr.io/cloud-builders/gcloud' args: ['app', 'deploy', 'app/app.yml'] env: ['GOPATH=/workspace']
これだけです。
GAEアプリケーションの作成
デプロイするにあたり、
先に空のアプリを作成する必要があります。
コンソールの右上にある、Cloud Shellの起動ボタンを押して、
Cloud Shellを起動します。
起動したら、以下のコマンドを実行します。
gcloud app create --region asia-northeast1
Success! The app is now created. Please use `gcloud app deploy` to deploy your first app.
と表示されれば、作成完了です。
Cloud Buildのサービスアカウント設定
最後に、Cloud BuildにGAEのデプロイをさせるための設定を行います。
IAMの画面で、
xxxxxxxxxxxxxx@cloudbuild.gserviceaccount.com
のアカウント(xxxxxxxxxxxxxxはそれぞれの環境で変わります)に、
以下の役割を追加してください。
- App Engine デプロイ担当者
- App Engine サービス管理者
こうすることで、Cloud BuildがGAEのデプロイとサービス更新を実行することができるようになります。
ここまでの設定が終わっていれば、
あとは前回設定したリポジトリにPushすれば、
自動でデプロイされて、
https://[プロジェクト名].appspot.com/
でアクセスできるようになっているはずです。
”Shaken, not stirred.”と表示されれば成功です。
アプリの中身を改修する
それでは、アプリの中身を書き換えて、
Slackからの一連の流れが成功するか確認してみましょう。
changeブランチを作成して、
app/main.goの19行目を以下のように書き換えます。
package main import ( "net/http" "html/template" "github.com/go-martini/martini" "log" ) func init() { m := martini.Classic() m.Get("/", index) http.Handle("/", m) } func index(w http.ResponseWriter, r *http.Request) { t := template.Must(template.ParseFiles("views/index/index.html.tpl")) str := "Name's Bond. James Bond." if err := t.ExecuteTemplate(w, "index.html.tpl", str); err != nil { log.Fatal(err) } }
プルリクエストを作成します。
Slackに表示されました!
Mergeボタンを押します!
すると、少したつと…
に変わりました!
[speech_bubble type=”std” subtype=”L1″ icon=”neko_03-1.png” name=””]韻を踏んでるにゃ[/speech_bubble]
[参考] GAE/Goにおける外部ライブラリの使用
Cloud Buildによるデプロイに限った話ではないのですが、
GAE/Goにおいて外部ライブラリを使用する際にハマった点について
説明を加えたいと思います。
通常、GoのソースコードでMartiniをimportするためには、
go get github.com/go-martini/martini
のようにして、GOPATHの配下にライブラリを取得した上でビルドする必要があります。
ただ、全てのライブラリで、上記のような操作をするのは煩雑ですし、
複数のライブラリのバージョンを使い分ける必要があった場合に困ります(いちいちGOPATHを切り替えたりする必要がある)。
そこで
Golangの開発チームが発表したライブラリ管理の仕組みとして最近注目されているdepがあります。
Rubyで言えばBundlerみたいなものです。
今回のアプリケーションでも、depを使ってライブラリの管理をしています。
depを使えば、
dep init
コマンドで、ソースコードのimport文を解析して、
使用しているライブラリの依存関係を自動で、
Gopkg.lock, Gopkg.tomlのファイルに定義してくれます。
また、同時にAPP_ROOT/vendor配下にビルドに必要なソースコードを配置してくれます。
(vendorのソースコードをgit管理下に置くべきか、という議論はありますが、
今回はgit管理下においてあります。)
このように便利なdepですが、
GAEで使うにあたって2点注意が必要でした。
1. gcloudでのデプロイがvendor配下を認識してくれない
gcloudでGAEにデプロイする際、
import文でMartiniをimportしようとしても、
2018/08/14 05:28:38 failed analyzing /workspace/app: cannot find package "github.com/go-martini/martini" in any of: ($GOROOT not set) /workspace/src/github.com/go-martini/martini (from $GOPATH) GOPATH: /workspace
とエラーが発生します。
どうやら、
GOPATH/src配下のものしかimport対象として認識してくれないようなので(つまり、公式のvendoringに完全に沿っていない)、
REPOSITORY_ROOT/src -> REPOSITORY_ROOT/app/vendorへのシンボリックリンクを作成して、
GOPATHを/worspaceに設定することで、importできるようにしました。
参考にさせていただいた記事:
[blogcard url=”https://medium.com/veltra-engineering/be-careful-when-deploying-golang-app-with-vendor-to-gae-4a12ad12b65f”]
2. ローカル実行時のvendor多重ビルド問題
もう一点、
app.yaml のあるディレクトリ以下に外部ライブラリのソースコードがあると、
多重ビルドが発生してしまって、ビルドエラーになるという問題があります。
app.yamlが置いてある階層以下に外部ライブラリのソースコードを置かないという方法もあるのですが、
depのライブラリ管理を使って、vendor配下にソースコードを配置しているのでその方法も難しいです。
というわけで、
app.yamlに
nobuild_files: vendor/
を追加することで、多重ビルドの問題を回避しました。
参考にさせていただいた記事:
[blogcard url=”https://motemen.hatenablog.com/entry/2016/11/gae-go-building”]
終わりに
さて、4回に渡ってSlackから、GAE/Goをデプロイする流れを実装してみました。
設定がすごく簡単にできることが、おわかりいただけたのではないかと思いますが、
いかがでしたでしょうか。
Cloud Buildは汎用性が高く、デプロイ以外にも様々な用途で利用可能ですし、
120分/日まで無料というのは魅力的です。
上記を超過した際のコストも、$0.0034 / 分というリーズナブルなお値段です。
ぜひ、有効に活用していきたいですね。