Posted at

GAE Nodeのgcp-buildでNuxt.jsのdeployを簡略化しようとして断念している話

これはGoogle Cloud Platform その2 Advent Calendar 2018 23日目の記事です。


tl;dr


  • GAE SE Nodeでgcp-buildを実行してくれるようになりました

  • でも使えていません←イマココ


倉科カナさんとわたし

ここは読み飛ばしてよいです

今日は12月23日です。

12月23日といえばみなさんはなにを思い浮かべますか?

天皇誕生日だから祝日だやっぽい!でしょうか?

しかしながらこの日誕生日を迎えるのはなにも天皇に限ったことではありません。

そうです、あの倉科カナさんのお誕生日でもあるのです:tada:

倉科さんとわたしは同郷(熊本出身)なのですが、なにを隠そう誕生日も一緒なのです:tada::tada:

これは運命かもしれません…!

ちなみに今年生まれた次女はカナと名付けました。

↓以下本文:bow:


GAE Node SE 10月のアップデート

今年(2018年)の10月31日、ベータリリース中のGAE Standard Environment Nodeについて以下のページでにアップデートが紹介されました。

Node.js 10 available for App Engine, in lockstep with Long Term Support | Google Cloud Blog

LTSになったNode10が使えるようになり、NPMしか使えなかったのがYarnもサポートされるようになりました。

あと地味な感じ(?)で以下もリリースされました。


Custom build step: If a script named gcp-build is present in package.json, this script will be executed at deployment time with access to dependencies declared in devDependencies.


package.jsonscripts.gcp-buildを書いておくと、gcloud app deploy時に実行してくれるというものです。


Nuxt.jsのbuildでgcp-buildを使ってみる

JSでSPA開発をしているとdeployの前にwebpack等でbuildする必要があると思います。

Nuxt.jsだとnuxt buildコマンドなどです。

gcp-build以前はCloud BuildやCircleCIなどで構築したdeploy pipeline上でこれを実行していたと思いますが、基本的には不要になります。

GAEで動かすためのNuxt.jsのサンプルリポジトリを用意しました。

https://github.com/iwata/nuxt-gae-se


package.json

{

"scripts": {
"gcp-build": "nuxt build",
...
},
...
}

gcp-buildの中でnuxt buildを実行するようにしています。

こうしておくことでdeploy時にはgcloud app deployだけを実行すればよくなります。

これでdeploy pipelineがかなりシンプルにできることが分かります。

cloudbuild.yamlで考えてみましょう。

gcp-build以前だと以下のようになります。


cloudbuild.yaml

steps:

- id: yarn-install
name: node:10
entrypoint: yarn
args: ['install']
- id: build
name: node:10
entrypoint: yarn
args: ['build']
- id: deploy
name: gcr.io/cloud-builders/gcloud
args:
- --quiet
- app
- deploy

それがgcp-buildを使うようにするとstepが1つだけになります。


cloudbuild.yaml

steps:

- id: deploy
name: gcr.io/cloud-builders/gcloud
args:
- --quiet
- app
- deploy

yarn install, yarn buildはFTL上で実行されるからです。便利ですね。

ちなみgcloud app deployでどういう処理が実行されているかはCloud BuildのHistoryが参照できるようになっています。

さきほどのrepositoryでdeployした場合のlogを一部抜粋すると以下のようになっています。

Step #1 - "builder": INFO yarn_run_gcp_build yarn run gcp-build

Step #1 - "builder": INFO `yarn_run_gcp_build` stdout:
Step #1 - "builder": yarn run v1.9.4
Step #1 - "builder": $ nuxt build
Step #1 - "builder": ℹ Production build 06:50:50
Step #1 - "builder": ✔ Builder initialized 06:50:50
Step #1 - "builder": ✔ Nuxt files generated 06:50:50
Step #1 - "builder": ℹ Compiling Client webpackbar 06:50:51
Step #1 - "builder": ✔ Client: Compiled successfully in 10.40s webpackbar 06:51:02
Step #1 - "builder": ℹ Compiling Server webpackbar 06:51:02
Step #1 - "builder": ✔ Server: Compiled successfully in 1.46s webpackbar 06:51:03
Step #1 - "builder": Done in 14.78s.

gcp-buildの中でnuxt buildが実行されていることがわかります。


gcp-buildのバグ

実はこのgcp-buildにはちょっと前までバグがありまして、実行されるときと実行されないときがありました。

Cloud Build上のログをみると分かるのですが、buildプロセスを一部キャッシュして高速化していることが分かります。

該当のログを抜粋

Step #1 - "builder": DEBUG Checking cache for cache_key b627ceb6e74444d52e3dc5d8d8271de93739a96cb207c4d9b0229b5629c7ddea

Step #1 - "builder": INFO Found cached base image: asia.gcr.io/serverless-test-sms/app-engine-tmp/build-cache/ttl-7d/node-cache:b627ceb6e74444d52e3dc5d8d8271de93739a96cb207c4d9b0229b5629c7ddea.
Step #1 - "builder": INFO Found cached dependency layer for b627ceb6e74444d52e3dc5d8d8271de93739a96cb207c4d9b0229b5629c7ddea
Step #1 - "builder": INFO {"architecture": "amd64", "author": "Bazel", "config": {}, "created": "2018-12-21T06:00:00Z", "history": [{"author": "Bazel", "created": "1970-01-01T00:00:00Z", "created_by": "bazel build ..."}], "os": "linux", "rootfs": {"diff_ids": ["sha256:16d82ecd2fbff51e859e0e6970a41792a84527b5427c1a0ea1081c31fe103535"]}}
Step #1 - "builder": INFO [CACHE][HIT] v0.13.0:NODE->b627ceb6e74444d52e3dc5d8d8271de93739a96cb207c4d9b0229b5629c7ddea
Step #1 - "builder": INFO checking_cached_packages_json_layer took 0 seconds
Step #1 - "builder": INFO starting: Building app layer
Step #1 - "builder": INFO starting: tar_runtime_package
Step #1 - "builder": INFO tar_runtime_package tar -pcf /tmp/tmpXmT14F.tar --transform flags=r;s,^,/srv/, --exclude *.pyc .

[CACHE][HIT]とあるとキャッシュが使われたことを意味するのですが、キャッシュヒット時にはgcp-buildが実行されないという状態でした。

ということでIssue Trakerにあげて対応してもらいました:smile:

[Standard Environment][Node] Not execute gcp-build [119335120] - Visible to Public - Issue Tracker

この修正がrolling outされたのがここ数日のようで試したところちゃんと動くようになっていました。


gcp-buildの要望

いまGAE上にNuxt.jsでSSRしているプロジェクトがあるのですが、実はまだgcp-buildを使えていません。

なぜかというと、gcp-build実行時に環境変数を指定できないからです。

いまnuxt build時にクライアントサイド用の環境変数を埋め込んでいるのですが、これは開発環境と本番環境で違う値を埋め込む必要があります。

サーバサイドではgcloud app deploy時に指定するapp.yamlを切り替えることで環境変数を切り替えています。(app.yamlとapp_dev.yamlなど)

gcp-build実行時にはapp.yamlenv_variablesをみてくれたりはしないので、gcp-build内で環境変数を指定するしかありません。


package.json

"scripts": {

"gcp-build": "cross-env APP_ENV=prod nuxt build"
}

こうするとpackage.jsonを置換したりする必要があります。

これはさすがにイケてないので移行できずにいます。

こちらもissue trackerにあげてはいますが対応されるのかは不明です。

[Standard Enviroment][Node] execute gcp-build with flexible environment variables [119568232] - Visible to Public - Issue Tracker1





  1. みなさんで要望挙げてもらうと積極的に対応されると思うんで追記お願いします:bow: