Cloud Build + Cloud DeployでNext.jsをデプロイする
この記事はコミューンプロダクト開発アドベントカレンダー2024のシリーズ1の2日目の記事です。
はじめに
Next.js アプリケーションを Cloud Run にデプロイしてみます。
デプロイには Cloud Build と Cloud Deploy を、データベースには Cloud SQL を使用します。
※本記事では、必要な API の有効化については省略しています。適宜設定してください。
構成図
以下の構成で、main ブランチへのプッシュをトリガーに Cloud Run へデプロイします。
サンプルアプリケーション
使用するアプリケーションはこちら: https://github.com/uyori/next-prisma-sample
- Next.js: v15.3
- Prisma: v6.0
- MySQL: v8.0.36
Cloud SQLの設定
1.インスタンスの作成
以下記事を参考に作成します。データベースエンジンは、MySQL 8.0を選択し、インスタンス名は next-prisma-instance で作成します。
2.データベースとユーザーの作成
作成したインスタンスにデータベースとユーザーを追加します。
- データベース: next-prisma-db
- ユーザー
- ユーザー名: app
- パスワード: password
3.テーブルの作成とサンプルデータの登録
Cloud SQL Studioにログインし、以下のSQLクエリを実行します。
-- Todos テーブルの作成
CREATE TABLE `Todos` (
`id` int NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`completed` tinyint(1) NOT NULL DEFAULT '0',
`createdAt` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updatedAt` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
PRIMARY KEY (`id`)
);
-- サンプルデータの登録
INSERT INTO `Todos` (`id`, `title`, `completed`) VALUES
(1, 'Buy milk', 0),
(2, 'Buy bread', 0),
(3, 'Buy eggs', 1);
4.Secret Managerに保存
データベースの接続情報を Secret Manager に保存します。
echo 'mysql://app:password@<プライベートIPアドレス>:3306/next-prisma-db' | \
gcloud secrets create db \
--data-file=-
※ <プライベートIPアドレス> は Cloud SQL インスタンスのプライベートIPアドレスに置き換えてください。
Cloud Buildの設定
1.Artifact Registoryの作成
デプロイする Docker イメージを保存するリポジトリを作成します。
$ gcloud artifacts repositories create next-prisma-repository \
--location=asia-northeast1 \
--repository-format=docker
2.Cloud Build Triggerの作成
まず、Cloud Build用のサービスアカウントを作成します。
gcloud iam service-accounts create next-prisma-cloud-build
gcloud projects add-iam-policy-binding <プロジェクトID> \
--member=serviceAccount:next-prisma-cloud-build@<プロジェクトID>.iam.gserviceaccount.com \
--condition=None \
--role=roles/logging.logWriter
gcloud projects add-iam-policy-binding <プロジェクトID> \
--member=serviceAccount:next-prisma-cloud-build@<プロジェクトID>.iam.gserviceaccount.com \
--condition=None \
--role=roles/cloudbuild.builds.builder
gcloud projects add-iam-policy-binding <プロジェクトID> \
--member=serviceAccount:next-prisma-cloud-build@<プロジェクトID>.iam.gserviceaccount.com \
--condition=None \
--role=roles/clouddeploy.releaser
gcloud projects add-iam-policy-binding <プロジェクトID> \
--member=serviceAccount:next-prisma-cloud-build@<プロジェクトID>.iam.gserviceaccount.com \
--condition=None \
--role=roles/iam.serviceAccountUser
*<プロジェクトID>は、自身のプロジェクトIDに置き換えてください。
コンソールからCloud Build Triggerを作成していきます。名前は next-prisma-trigger で、リージョンは global を選択します。
trigger対象となるリポジトリ(next-prisma-sample)を選択し、構成からCloud Build 構成ファイルを選択します。
先ほど作成したサービスアカウントを設定し、保存します。
3.cloudbuild.yaml の作成
以下の cloudbuild.yaml をプロジェクトルートに作成します。
steps:
- id: build
name: 'gcr.io/cloud-builders/docker'
args:
- build
- '-t'
- 'asia-northeast1-docker.pkg.dev/${PROJECT_ID}/next-prisma-repository/app:${SHORT_SHA}'
- '.'
- id: push
name: 'gcr.io/cloud-builders/docker'
args:
- push
- 'asia-northeast1-docker.pkg.dev/${PROJECT_ID}/next-prisma-repository/app:${SHORT_SHA}'
- id: deploy
name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: 'gcloud'
args:
- deploy
- releases
- create
- 'release-${SHORT_SHA}'
- '--delivery-pipeline'
- 'next-prisma-pipeline'
- '--region'
- 'asia-northeast1'
- '--images'
- 'app=asia-northeast1-docker.pkg.dev/${PROJECT_ID}/next-prisma-repository/app:${SHORT_SHA}'
options:
logging: 'CLOUD_LOGGING_ONLY'
- build ステップ:
- Docker イメージをビルドします
-
$PROJECT_ID
はCloud プロジェクトのIDで、$SHORT_SHA
はビルドに関連付けられたコミットIDで置換されます(https://cloud.google.com/build/docs/configuring-builds/substitute-variable-values?hl=ja)
- push ステップ:
- ビルドしたイメージを Artifact Registry にプッシュします。
- deploy ステップ:
- Cloud Deploy を使用してリリースを作成します
Cloud Deployの設定
1.デリバリーパイプラインの作成
まず、Cloud Build用のサービスアカウントを作成し、権限を付与します。
gcloud iam service-accounts create next-prisma-cloud-deploy
gcloud projects add-iam-policy-binding <プロジェクトID> \
--member=serviceAccount:next-prisma-cloud-deploy@<プロジェクトID>.iam.gserviceaccount.com \
--condition=None \
--role=roles/logging.logWriter
gcloud projects add-iam-policy-binding <プロジェクトID> \
--member=serviceAccount:next-prisma-cloud-deploy@<プロジェクトID>.iam.gserviceaccount.com \
--condition=None \
--role=roles/storage.objectUser
gcloud projects add-iam-policy-binding <プロジェクトID> \
--member=serviceAccount:next-prisma-cloud-deploy@<プロジェクトID>.iam.gserviceaccount.com \
--condition=None \
--role=roles/run.developer
gcloud projects add-iam-policy-binding <プロジェクトID> \
--member=serviceAccount:next-prisma-cloud-deploy@<プロジェクトID>.iam.gserviceaccount.com \
--condition=None \
--role=roles/iam.serviceAccountUser
次に、Cloud Runをデプロイ先ターゲットとするデリバリーパイプラインを作成します。
以下の clouddeploy.yaml をプロジェクトルートに作成します。
apiVersion: deploy.cloud.google.com/v1
kind: DeliveryPipeline
metadata:
name: next-prisma-pipeline
serialPipeline:
stages:
- targetId: next-prisma-target
---
apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
name: next-prisma-target
run:
location: projects/<プロジェクトID>/locations/asia-northeast1
- usages:
- RENDER
- DEPLOY
serviceAccount: next-prisma-cloud-deploy@<プロジェクトID>.iam.gserviceaccount.com
以下のコマンドを実行し、実際にデリバリーパイプライン及びターゲットを作成します。
gcloud deploy apply \
--file=clouddeploy.yaml \
--region asia-northeast1
2.skaffold.yamlの作成
Cloud Deployに必要なskaffold.yamlを、プロジェクトのルートディレクトリに作成します。
apiVersion: skaffold/v4beta5
kind: Config
metadata:
name: next-prisma
manifests:
rawYaml:
- ./cloudrun.yaml
deploy:
cloudrun: {}
3.service.yamlの作成
Cloud Run用のサービスアカウントを作成し、Secret Managerにアクセスするための権限を付与します。
gcloud iam service-accounts create next-prisma-app
gcloud secrets add-iam-policy-binding db \
--member=serviceAccount:next-prisma-app@<プロジェクトID>.iam.gserviceaccount.com \
--role=roles/secretmanager.secretAccessor
Skaffold がデプロイする Cloud Run サービスを定義したservice.yamlを作成します。
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: next-prisma-app
spec:
template:
metadata:
annotations:
# Cloud SQL の VPC、サブネットを設定
run.googleapis.com/network-interfaces: '[{"network":"default","subnetwork":"default"}]'
spec:
containers:
- image: app
ports:
- name: http1
containerPort: 3000
# 環境変数DATABASE_URLに、secretManagerに登録したdbの接続情報を設定
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
key: 1
name: db
startupProbe:
tcpSocket:
port: 3000
さいごに
Cloud Build と Cloud Deploy を使用して Next.js アプリケーションを Cloud Run にデプロイすることができました。今後は GoogleCloud のリソースを Terraform で構築していきたいです💪
参考
Discussion