🙆

Next.jsをGAEで動かす(CloudBuildから自動デプロイ)

5 min read

Next.jsアプリをGoogle App Engine(GAE)のスタンダード環境にデプロイする方法をまとめておきます。GitHubなどからCI/CDができるようにGoogle Cloud Buildから自動デプロイする方法も合わせて紹介します。

最初はGAEのNode.jsランタイムがデプロイ時にnpm installnpm run gcp-buildを実行してくれるのを活かしてデプロイしようとしたのですが、なぜかうまくいきませんでした。同じ問題に直面する方もいるかもしれないと思い一応スクラップにまとめておきました。

Next.js on GAEで失敗したデプロイ設定を供養する

Next.jsアプリがすでに作成されているという前提で説明をはじめます。

1. app.yamlの設定

まずはプロジェクト内のルートなどにapp.yamlを作成します。GAEへのデプロイ設定の大部分はここで行います。今回は例として以下のようにします。

app.yaml
env: standard # スタンダード環境(省略可)

runtime: nodejs14 # Node.js 14を使う

instance_class: F4

service: default # GAEのサービスの名前。frontendとかでも良いかも

handlers:
  - url: /_next/static
    static_dir: .next/static
  - url: /(.*\.(gif|png|jpg|ico|txt|svg))$
    static_files: public/\1
    upload: public/.*\.(gif|png|jpg|ico|txt|svg)$
  - url: /.*
    script: auto
    secure: always

default_expiration: "12h" # 静的ファイルのキャッシュ期間

env_variables:
  NODE_ENV: "production"

automatic_scaling:
  min_instances: 0 # 動かしてないときはインスタンスを0にする

簡単に説明をしておきます

  • instance_class: F4だと メモリ 1024 MB / CPU 2.4 GHz という制限になります。他の設定値はインスタンスのクラスをどうぞ。
  • handlersではURLのパターンごとの処理を設定します。
    • static_dirstatic_filesにマッチしたファイルは静的ファイルとしてアップロードされるようになります(詳細
    • Next.jsのデフォルト設定ではビルド時に静的ファイルが.next/staticディレクトリの中に出力されるようになっています(参考)。
    • Next.jsではpublicディレクトリ内に静的ファイルを入れることができます。実際のファイルへのURLには/publicがつかずルートからの参照になるため、指定がややこしくなります。今回はNuxt.jsのドキュメントを参考に指定しました。
  • 静的ファイルのキャッシュ期間はdefault_expirationで指定できます。今回は12h(12時間)としてみました。
  • automatic_scalingでは最小インスタンス数や最大インスタンス数などを指定できます。ドキュメントを参考により細かな設定を行うことをおすすめします。

2. package.jsonの設定

package.json
{
   "scripts": {
     "dev": "next dev",
+    "build": "next build",
+    "start": "next start -p $PORT",  
   },
}

GEAでNext.jsを動かすには、ビルドした上でnext startを実行することになります。GAEではpackage.jsonstartスクリプトが書かれていると、アプリ起動時に実行してくれます。

デフォルトでは、ランタイムは node server.js を実行してアプリケーションを起動します。package.json ファイルで start スクリプトを指定すると、ランタイムは代わりに指定された起動スクリプトを実行します。
アプリケーションの起動

3. .gcloudignoreの設定

.gcloudignoreには、サービスをデプロイするときにGAEにアップロードしないファイルを指定します。詳しい書き方はこちらの記事が参考になります。

https://zenn.dev/satohjohn/articles/11df180df878ac

たとえば以下のように指定します。

.gcloudignore
.gcloudignore
.gitignore

node_modules/

これに加えて/components/pagesなどのビルド後は不要になるソースファイルも.gcloudignoreに追加できます。これらのファイルを/srcディレクトリにまとめている場合は/srcを追記すればOKです。

4. ローカルからのデプロイを試す

ここまで設定ができていればビルドしてデプロイができます。ローカルからデプロイするにはgcloud CLIのセットアップが完了している必要があります。

$ npm run build
$ gcloud app deploy app.yaml --project GCPのプロジェクト名

以下のようにpackage.jsonにデプロイ用のscriptを追加しておいても良いと思います。

package.json
{
   "scripts": {
+    "deploy:gae": "npm run build && gcloud app deploy app.yaml --project=プロジェクト名",  
   },
}

これでローカルからはnpm run deploy:gaeでデプロイができるようになります。

5. CloudBuildからのデプロイ

CloudBuildからGAEするためにはサービスアカウントのIAM設定が必要です。このあたりはドキュメントで分かりやすく解説されています。

https://cloud.google.com/source-repositories/docs/quickstart-triggering-builds-with-source-repositories?hl=ja

cloudbuild.yaml

ステップの中でnpm installnpm run buildを実行したうえでGAEのデプロイコマンドを叩くようにします。

cloudbuild.yaml
steps:
  - name: node
    entrypoint: npm
    args: ["install"]
  - name: node
    entrypoint: npm
    args: ["run", "build"]
  - name: gcr.io/cloud-builders/gcloud
    args: ["app", "deploy", "app.yaml", "--project=foo", "--quiet"]

--quietはデプロイ時に表示される「デプロイしますか?」のような確認をスキップするために指定します。

CloudBuildのステップでyarnを使う場合

パッケージのインストールやビルドにyarnを使いたい場合はentrypointyarnにします。

cloudbuild.yaml
steps:
  - name: node
    entrypoint: yarn
    args: ["install"]
  - name: node
    entrypoint: yarn
    args: ["build"]
  - name: gcr.io/cloud-builders/gcloud
    args: ["app", "deploy", "app.yaml", "--project=foo", "--quiet"]

nodeバージョンを指定したい場合

Node.jsのバージョンを指定したい場合はnameの値をnode:バージョンとします。

cloudbuild.yaml
  - id: install-packages
    name: node:14
    entrypoint: yarn
    args: ["install"]

以上の設定ができていれば、CloudBuildからGAEへのデプロイができるはずです。

Discussion

ログインするとコメントできます