Next.jsのNEXT_PUBLIC環境変数をCloud Build + Cloud Run + Terraformで管理する方法
Updated Date: 2026/03/04 23:14
GCPでNext.jsをCloud Runにデプロイする際、NEXT_PUBLIC_ から始まる環境変数の扱いでハマったので、解決策と設定全体像をまとめておく。
NEXT_PUBLIC変数が特殊な理由
Next.jsにはサーバー専用の環境変数と、クライアントにも公開される環境変数の2種類がある。
| 種類 | 例 | 埋め込みタイミング |
|---|---|---|
| サーバー専用 | API_SECRET_KEY |
ランタイム(コンテナ起動時) |
| クライアント公開 | NEXT_PUBLIC_API_URL |
ビルド時にソースへ静的埋め込み |
問題はここ。 バックエンドAPIなら docker run -e API_KEY=xxx のように起動時に環境変数を渡せばよいが、NEXT_PUBLIC_ 変数は next build 実行時にバンドルに書き込まれる ため、ビルド前に値が確定していなければならない。
つまり、Cloud RunのコンソールやTerraformで「実行時環境変数」として設定しても NEXT_PUBLIC_ には反映されない。
最初のアプローチとその問題点
最初に試みた構成:
| ステップ | 担当 | 内容 |
|---|---|---|
| 1 | Terraform | 環境変数を定義 |
| 2 | Cloud Build (cloudbuild.yaml) | docker build時に --build-arg でDockerfileに渡す |
| 3 | Dockerfile | ARG で受け取り ENV に設定 |
| 4 | Cloud Run | 設定なし |
この方法の問題は、環境変数を追加・変更するたびに Terraform・cloudbuild.yaml・Dockerfile の3箇所を修正しなければならない 点。変更漏れによるバグが起きやすい。
改善後の構成
yarn build(つまり next build)を Dockerビルドの前 にCloud Build上で実行することで、Dockerfileを環境変数の設定から切り離した。
| ステップ | 担当 | 内容 |
|---|---|---|
| 1 | Terraform | 環境変数を定義 |
| 2 | Cloud Build | yarn build に環境変数を渡してビルド → そのままDockerイメージ化 |
| 3 | Dockerfile | 設定不要 |
| 4 | Cloud Run | 設定不要 |
修正が必要な箇所が 2箇所(TerraformとCloud Build) だけになった。
実装詳細
cloudbuild.yaml の設定
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
28
29
30
31
32
33
34
35
steps:
# Step 1: yarn buildしてNEXT_PUBLICをビルド時に埋め込む
- 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_API_URL=$$API_URL'
secretEnv:
- 'FIREBASE_API_KEY'
- 'FIREBASE_APP_ID'
# Step 2: ビルド済みの成果物をそのままDockerイメージにまとめる
- id: 'build'
name: 'gcr.io/cloud-builders/docker'
entrypoint: 'sh'
args:
- '-c'
- |
docker build \
--cache-from gcr.io/$PROJECT_ID/my-app:latest \
-f ./docker/Dockerfile \
-t gcr.io/$PROJECT_ID/my-app:latest \
.
waitFor:
- 'yarn build'
availableSecrets:
secretManager:
- versionName: projects/$PROJECT_ID/secrets/FIREBASE_API_KEY/versions/latest
env: 'FIREBASE_API_KEY'
- versionName: projects/$PROJECT_ID/secrets/FIREBASE_APP_ID/versions/latest
env: 'FIREBASE_APP_ID'
ポイントは $$VARIABLE_NAME という二重ドルの記法。Cloud Buildでは $VAR はCloud Build組み込み変数、$$VAR はSecret Managerや置換変数を参照するための記法。
Terraform での Secret Manager 設定例
1
2
3
4
5
6
7
8
9
10
11
resource "google_secret_manager_secret" "firebase_api_key" {
secret_id = "FIREBASE_API_KEY"
replication {
auto {}
}
}
resource "google_secret_manager_secret_version" "firebase_api_key" {
secret = google_secret_manager_secret.firebase_api_key.id
secret_data = var.firebase_api_key
}
.gitignore の注意点
next build の成果物(.next/ ディレクトリ)をCloud Build上で生成してDockerイメージに含めるため、.gitignore から除外されていても問題ない(Cloud Build上でのみ生成・使用)。ただし、ローカルで誤ってコミットしないよう .gitignore には引き続き記載しておくこと。
1
2
.next/
out/
セキュリティ上の注意
NEXT_PUBLIC_ 変数はブラウザのJavaScriptバンドルに平文で埋め込まれるため、公開しても問題のない値のみを設定すること。APIシークレットキーや認証情報を誤って NEXT_PUBLIC_ で定義しないよう注意。
まとめ
Next.jsの NEXT_PUBLIC_ 環境変数はビルド時埋め込みのため、Cloud Runの実行時環境変数では反映されない。Cloud Build上で next build を先に実行してからDockerイメージを作ることで、環境変数管理をシンプルにできる。
ビルドサービス(Cloud Build)のリソースを活用してビルドを行うことで、Dockerfileをシンプルに保つのがポイント。