2023 部署 Next.js 至 Google Cloud Run (混搭 Cloud Build, Gitlab CI, Secret Manager)
本文的核心為將 Next.js 部署至 Google Cloud Run,CI 的部分會使用 Gitlab CI,主要會依據採用不同服務分成兩種流程:
- 在 Gitlab CI 建置 Docker Image 暫存到 Gitlab 後續部署到 Cloud Run
- Gitlab CI 搭配 Cloud Build 部署到 Cloud Run
本文希望可以儘量補充其他教學遺失的環節,幫助您可以自行選擇想用的服務調整流程。
[toc]
使用 Gitlab CI 建置 Docker Image 暫存到 Gitlab 後續部署至 Cloud Run
1. 建立 Next.js 專案
1 | $ npx create-next-app [PROJECT_NAME] |
2. Docker 化 Next.js 專案
在 Next.js 專案根目錄下
1 | $ touch Dockerfile |
下面
Dockerfile
是參考官方範例修改而成的。隨著時間演進可能有所不同,建議您可以也可以一起參考官方的範例調整。另外,為了減少正式環境建置檔案大小複製了
/app/.next/standalone
則next.config.js
須增加設定output: "standalone"
1
2
3
4
5
6
7 /** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
output: "standalone",
};
module.exports = nextConfig;
Dockerfile
如下,採用複數 Stage / Layer 的理由是為了縮小最後 Image 的大小:
1 | # 安裝相依套件 |
完成 Dockerfile
之後可以執行 docker build
和 docker run
進行本地測試
1 | $ docker build -t andyyou/nextjs . |
現在您可以瀏覽 http://localhost:3000
它會顯示跟之前本地開發伺服器一樣的內容。
到此我們已經成功的 Docker 化一個 Next.js 應用程式。另外建議您可以閱讀 Nodejs 與 Docker。
3. 設定 Google Cloud Service
這個 CI 流程大部分我們都在 Gitlab 處理,會用到 GCP 的部分只有 Cloud Run,但在發佈的過程我們會需要一組 Service Account 的金鑰。因此本節的設定:
- 建立 GCP 專案
- 啟用 Cloud Run API
- 建立授權一組 Service Account 並取得 JSON Key
GCP 權限部分:
- Editor - 允許 Service Account 啟用/停用 API 或從 Google Cloud SDK 安裝更新
- Cloud Run Admin - 允許 Service Account 執行 Cloud Run 指令,例如
deploy
應用程式- Storage Admin - 允許 Service Account 推送
push
Docker Image 到 Google Container Registry- Service Account User - 允許 Service Account 在 Cloud Run 中使用 Service Account 部署
備註:關於權限的部分可以依據您的需求調整,此處僅為展示。
4. 建立 .gitlab-ci.yml
在開始撰寫 .gitlab-ci.yml
之前,請先建立好我們的 Gitlab Repository ,我們還需要將 Cloud Run 的服務名稱,Google Project ID,Service Account 金鑰設到 Gitlab ,如此 CI 才能讀取相關資料。
登入 Gitlab > 專案 > 左邊選單 Settings > CI/CD > Variables 新增變數。下面變數您應該可以在 GCP Console 以及剛剛下載的 JSON 取得。GCP_CLOUD_RUN_SERVICE_NAME
您可以自訂就是這個專案服務的名稱。
如果要在其他分支使用變數記得取消
Protect variable
。
GCP_SERVICE_KEY
GCP_PROJECT_ID
GCP_CLOUD_RUN_SERVICE_NAME
接著,我們就可以使用 Gitlab CI 將 Next.js 專案部署到 Cloud Run 了
1 | $ touch .gitlab-ci.yml |
.gitlab-ci.yml
檔案如下:
1 | image: docker |
然後您就可以到 Gitlab > CI/CD > Pipeline 去發佈。
5. 補充 - 環境變數處理
假設您沒有把 .env
相關的檔案 commit 到 Git 檔案庫上。上面的範例遺漏了一個沒有處理的部分,Next.js 在建置時期會無法取得環境變數,導致前端部分無法使用,即便您後來在 Cloud Run 介面補上這些變數也無法讀取。
這裡提供一個簡單的方式即先將變數以 VAR1=a,VAR2=b,VAR3=c 的格式儲存到 Gitlab 的 CI/CD 環境變數。然後利用 --build-arg
參數將變數傳入 Docker 建置流程,在稍微變更一下 Dockerfile
來處理。下面為兩個設定檔案
這裡示範補上一個 NEXT_ENV
環境變數。
Dockerfile
的部分注意 RUN npm run build
之前補上 ARG
等
1 | // ... |
.gitlab-ci.yml
則在 build
階段補上 --build-arg
1 | build: |
進階 - 使用 Gitlab CI 搭配 Google Cloud Build 部署至 Cloud Run
開始前概略介紹
- Cloud Run 是一個託管計算平台,提供自動擴展無狀態,無伺服器的容器
- Cloud Build 是一個服務,可以在 Google Cloud Platform 執行編譯建置的任務
- Gitlab CI 是 Gitlab 服務的一部分,可以在開發者將程式碼推送到檔案庫時建置和測試軟體
本節和上一節的差異為這次我們不在 Gitlab 編譯 Docker Image 而是將任務直接交給 Cloud Build 後續的部署也是一樣都由 Cloud Build 處理。以及我們會使用 Secret Manager 來處理正式環境的環境變數。
1. 設定 Google Cloud Service
- 如果您還沒有 GCP 專案請先建立專案,或參考上面章節。
- 啟用 Cloud Build
- 啟用 Cloud Run API
- 啟用 Secret Manager
- 登入您的 GCP 切換至 Cloud Build > Settings,在 Service account permissions 下面確認 Cloud Run & Service Accounts & Secret Manager Secret Accessor 為 ENABLED
- 參考上面建立 Service Accout 的步驟不過這次我們需要的權限是
Cloud Build Service Agent
和Secret Manager Secret Accessor
,一樣取得 JSON 檔案。您也可以直接至 Google IAM 去調整。 - 登入 GCP > Secret Manager > Create Secret > 使用
VAR1=a,VAR2=b,VAR3=c
格式建立您的環境變數。
2. 建立或使用既有 Next.js 專案
您可以參考上面章節建立專案或使用既有的專案。除此之外我們還需要
3. 設定 Gitlab CI/CD, Cloud Build 與 Docker
從上概覽,整個流程的順序會是我們靠 .gitlab-ci.yml
使用 gcloud builds submit
將 cloudbuild.yaml
腳本和專案本身一併交給 Cloud Build。然後 Cloud Build 依據 cloudbuild.yaml
- 讀取 Secret Manager 的資料
- 建置 Docker Image
- 推送 Docker Image 到 Registry
- 使用
gcloud
指令部署到 Cloud Run
第一步我們先搞定 Gitlab CI,一樣到 Gitlab 專案下左邊選單 Settings > CI/CD > Variables 設定環境變數
- GCP_SERVICE_KEY
- GCP_PROJECT_ID
1 | $ touch .gitlab-ci.yml |
.gitlab-ci.yml
檔案如下
1 | image: google/cloud-sdk:slim |
注意到這裡我們使用 Google 的 Image 支援 gcloud
相關指令。如果您希望在 Gitlab 這邊也增加 test
和 build
階段可以自行增加。我們這裡單純演示使用 Cloud Build 的部分。
4. 建立 cloudbuild.yaml
接著我們新增 cloudbuild.yaml
檔案如下。注意 Secret Manager 的使用。您可以閱讀一下官方文件,有個重點 -c
後面的指令是不可以拆開的。
1 | steps: |
5. 調整 Dockerfile
1 | # 安裝相依套件 |
到此推送到 Gitlab 之後就可以部署了。本文的使用範例都是經過測試,希望可以提供一些幫助。
另外,兩個方式都是使用 --build-arg
的方式傳遞,如果您專精 Docker 有更好的作法歡迎告訴我 XD。
參考資源
2023 部署 Next.js 至 Google Cloud Run (混搭 Cloud Build, Gitlab CI, Secret Manager)
https://andyyou.github.io/2023/01/12/deploy-nextjs-to-cloud-run-with-gitlab-ci/