bon now

ありのままの現実を書き殴る吐き溜め。底辺SEの備忘録。
Written by bon who just a foolish IT Engineer.

Next.jsアプリをTerraformとCloudBuildを使ってCloud Runで動かす

Created Date: 2022/08/03 02:47
Updated Date: 2023/07/03 19:46

自社ではGCPを使ってNext.jsのSSGをフロントエンドサーバーとしてCloud Runで動かしている。
バックエンドのデプロイの仕組みはわかっているつもりだったが、Next.jsの環境変数の設定周りで苦労したので知見として残しておく。

何が起きたか

ありのまま起こったことを話すと、Next.jsのWebサービスは NEXT_PUBLIC から始まる環境変数を持っていて、これがアプリのビルド時に環境変数にとして埋め込まれる。
つまり、バックエンドの実装の場合、基本的にDockerコンテナを動かすときに環境変数を渡せばよいのだが、Next.jsだとそうはいかないということだ。

なので、以下のような構成で環境変数を設定するようにした。

# サービス名 内容
1 Terraform 使う環境変数を定義(1)
2 Cloud build(cloudbuild.yaml) (1)で定義した環境変数をdocker build時に設定(2)
3 Dockerfile (2)の環境変数をARGで受け取りENVに設定するよう記述
4 Cloud Run 何も設定なし

ややこしいポイント

この仕組みだとNEXT_PUBLIC系の環境変数を追加・削除するときは3回箇所(1,2,3)も編集しなければならない。 これがわりとややこしい。

改善案

ということで改善案がこちら。

# サービス名 内容
1 Terraform 使う環境変数を定義(1)
2 Cloud build(cloudbuild.yaml) (1)で定義した環境変数をenvに指定
3 Dockerfile 何も設定無し
4 Cloud Run 何も設定なし

1つステップが減った。これによりTerraformとcloudbuild.yamlのみを修正するだけで良くなった。どういうことか説明するために cloudbuild.yml の一部を抜粋する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- id: 'yarn build'
  name: node
  entrypoint: yarn
  args: ['run', 'build']
  env:
    - 'NEXT_PUBLIC_FIREBASE_API_KEY=$$FIREBASE_API_KEY'
    - 'NEXT_PUBLIC_FIREBASE_APP_ID=$$FIREBASE_APP_ID'
    - 'NEXT_PUBLIC_TEST_ENV=$$TEST_ENV'
  secretEnv: [
    'FIREBASE_API_KEY',
    'FIREBASE_APP_ID',
  ]

- id: 'build'
  name: 'gcr.io/cloud-builders/docker'
  entrypoint: 'sh'
  args: [
    '-c',
    'docker build
      --cache-from hoge-app:latest
      --build-arg PORT="3335"
      -f ./docker/Dockerfile
      -t hoge-app:latest
      .'
  ]
  waitFor:
    - 'yarn build'

つまり ソースをyarn buildして環境変数を埋め込む → それをDockerコンテナとしてまとめる ということをやっている。
このとき、 .gitignore から .next ディレクトリや out などNext.js・TypeScriptのbuild時の出力ディレクトリを除くことを忘れてはならない。

まとめ

Dockerサイコー!という感じでなんでもDocker化せず、仕組みを簡素化するために、有り余るビルドサービス側の資源を活用するのも方法の1つ。 ちなみにビルド時間はそんなに変わらないと思う。

local_offer
gcp
folder work