その他
    ホーム 技術発信 あぴらぼ式 Cloud BuildでGAE/Goデプロイ by Slack vol.4
    Cloud BuildでGAE/Goデプロイ by Slack vol.4
     

    Cloud BuildでGAE/Goデプロイ by Slack vol.4

    Information

    この記事はアピリッツの技術ブログ「あぴらぼ式」から移行した記事です。情報が古い可能性がありますのでご注意ください。

    前回 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 / 分というリーズナブルなお値段です。

    ぜひ、有効に活用していきたいですね。

    記事を共有