Next.jsをGAEで動かす(CloudBuildから自動デプロイ)
Next.jsアプリをGoogle App Engine(GAE)のスタンダード環境にデプロイする方法をまとめておきます。GitHubなどからCI/CDができるようにGoogle Cloud Buildから自動デプロイする方法も合わせて紹介します。
Next.jsアプリがすでに作成されているという前提で説明をはじめます。
1. app.yamlの設定
まずはプロジェクト内のルートなどにapp.yamlを作成します。GAEへのデプロイ設定の大部分はここで行います。今回は例として以下のようにします。
env: standard # スタンダード環境(省略可)
runtime: nodejs14 # Node.js 14を使う(追記: nodejs16も使えるようになりました)
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_dirやstatic_filesにマッチしたファイルは静的ファイルとしてアップロードされるようになります(詳細) - Next.jsのデフォルト設定ではビルド時に静的ファイルが
.next/staticディレクトリの中に出力されるようになっています(参考)。 - Next.jsでは
publicディレクトリ内に静的ファイルを入れることができます。実際のファイルへのURLには/publicがつかずルートからの参照になるため、指定がややこしくなります。今回はNuxt.jsのドキュメントを参考に指定しました。
-
- 静的ファイルのキャッシュ期間は
default_expirationで指定できます。今回は12h(12時間)としてみました。 -
automatic_scalingでは最小インスタンス数や最大インスタンス数などを指定できます。ドキュメントを参考に、より細かな設定を行うことをおすすめします。
2. package.jsonの設定
{
"scripts": {
"dev": "next dev",
+ "build": "next build",
+ "start": "next start -p $PORT",
},
}
GEAでNext.jsを動かすには、ビルドした上でnext startを実行することになります。GAEではpackage.jsonにstartスクリプトが書かれていると、アプリ起動時に実行してくれます。
デフォルトでは、ランタイムは node server.js を実行してアプリケーションを起動します。package.json ファイルで start スクリプトを指定すると、ランタイムは代わりに指定された起動スクリプトを実行します。
アプリケーションの起動
3. .gcloudignoreの設定
.gcloudignoreには、サービスをデプロイするときにGAEにアップロードしないファイルを指定します。詳しい書き方はこちらの記事が参考になります。
たとえば以下のように指定します。
.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を追加しておいても良いと思います。
{
"scripts": {
+ "deploy:gae": "npm run build && gcloud app deploy app.yaml --project=プロジェクト名",
},
}
これでローカルからはnpm run deploy:gaeでデプロイができるようになります。
5. CloudBuildからのデプロイ
CloudBuildからGAEするためにはサービスアカウントのIAM設定が必要です。このあたりはドキュメントで分かりやすく解説されています。
cloudbuild.yaml
ステップの中でnpm installとnpm run buildを実行したうえでGAEのデプロイコマンドを叩くようにします。
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を使いたい場合はentrypointをyarnにします。
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:バージョンとします。
- id: install-packages
name: node:14
entrypoint: yarn
args: ["install"]
以上の設定ができていれば、CloudBuildからGAEへのデプロイができるはずです。
Discussion