1. 系統架構概要#
- Source: 私人託管 Gitea (透過 SSH Key 驗證)。
- CI/CD: Cloud Build 執行
cloudbuild.yaml進行 Docker 打包。 - Storage: Artifact Registry 儲存 Docker 鏡像。
- Compute: Cloud Run 執行服務。
- Network:
- VPC Connector: 作為 Cloud Run 進入 VPC 的橋樑。
- Cloud NAT: 強制所有出口流量經由固定公網 IP 發出。
2. 環境準備與權限設定 (IAM)#
在開始自動化之前,必須確保 Cloud Build 服務帳號 擁有足夠權限。
請前往「IAM 與管理員」,尋找 [專案編號]@cloudbuild.gserviceaccount.com 並授予:
- Cloud Run Admin: 部署服務至 Cloud Run。
- Service Account User: 代表服務帳號執行任務。
- Secret Manager Secret Accessor: 讀取 Gitea SSH Key。
- Artifact Registry Administrator: 上傳 Docker 鏡像。
3. Gitea 私人託管連結設定#
由於私人 Gitea 無法直接連結,須使用 Secret Manager 存儲 SSH Key。
- 產生金鑰: 在本地產生 SSH Key 對,並將 Public Key 加入 Gitea。
- 存儲私鑰: 將 Private Key 存入 Google Secret Manager,命名為
GITEA_SSH_KEY。
4. 自動化配置檔案 (cloudbuild.yaml)#
在專案根目錄建立此檔案:
_43steps:_43 # 1. 透過 Secret Manager 取得 SSH Key 並 Clone 程式碼_43 - name: 'gcr.io/cloud-builders/git'_43 secretEnv: ['SSH_KEY']_43 entrypoint: 'bash'_43 args:_43 - '-c'_43 - |_43 mkdir -p /root/.ssh_43 echo "$$SSH_KEY" > /root/.ssh/id_rsa_43 chmod 400 /root/.ssh/id_rsa_43 ssh-keyscan <你的_GITEA_域名或IP> >> /root/.ssh/known_hosts_43 git clone --depth 1 git@<你的_GITEA_域名>:<用戶名>/<專案名>.git ._43 volumes:_43 - name: 'ssh'_43 path: /root/.ssh_43_43 # 2. 構建 Docker 鏡像_43 - name: 'gcr.io/cloud-builders/docker'_43 args: ['build', '-t', 'asia-east1-docker.pkg.dev/$PROJECT_ID/repo/image:$COMMIT_SHA', '.']_43_43 # 3. 推送到 Artifact Registry_43 - name: 'gcr.io/cloud-builders/docker'_43 args: ['push', 'asia-east1-docker.pkg.dev/$PROJECT_ID/repo/image:$COMMIT_SHA']_43_43 # 4. 部署到 Cloud Run (注意:此處不設定 egress 以避免部署卡住)_43 - name: 'gcr.io/[google.com/cloudsdktool/cloud-sdk](https://google.com/cloudsdktool/cloud-sdk)'_43 entrypoint: gcloud_43 args:_43 - 'run'_43 - 'deploy'_43 - 'nuxt-service'_43 - '--image'_43 - 'asia-east1-docker.pkg.dev/$PROJECT_ID/repo/image:$COMMIT_SHA'_43 - '--region'_43 - 'asia-east1'_43 - '--vpc-connector'_43 - 'nuxt-vpc-connector'_43_43availableSecrets:_43 secretManager:_43 - env: 'SSH_KEY'_43 versionName: projects/$PROJECT_ID/secrets/GITEA_SSH_KEY/versions/latest
5. 關鍵:固定出口 IP (Egress) UI 設定建議#
實務經驗: 直接在 YAML 或 gcloud 指令中變更 --egress-settings 經常會導致部署進度卡死或報錯。建議在第一次部署成功後,透過 GCP 控制台進行一次性手動設定。
部署成功後,進入 Cloud Run 控制台。
點擊服務名稱 -> 點擊上方 「編輯並部署新的修訂版本」。
下拉至 「網路 (Networking)」 頁籤。
在 VPC 連線 部分,確認已選取正確的 Connector。
在下方 流量路徑 (Egress settings) 勾選:「將所有流量路由至 VPC (Route all traffic to the VPC)」。
點擊最下方的 「部署」。
6. 部署常見問題彙整 (Troubleshooting)#
Q1: Cloud Build 部署過程無限卡住或失敗 原因: YAML 指令嘗試同時更新 Egress 與 Connector 資源,導致底層部署 API 衝突。
解決: 移除 YAML 中的 egress 參數,改由 GCP UI 手動勾選 (如第 5 步所述)。
Q2: Nuxt 專案啟動後讀不到 API URL 或環境變數 原因: 變數未對應到 Nuxt 的 Runtime Config。
解決:
檢查 nuxt.config.ts 內是否有定義 runtimeConfig.public。
確認 Cloud Run 的環境變數名稱是否帶有 NUXT_PUBLIC_ 前綴。
如果在 nitro.routeRules 使用代理,請確保使用 process.env 讀取。
Q3: Gitea Clone 失敗 (Permission Denied) 原因: 服務帳號權限不足或 SSH Key 格式/路徑錯誤。
解決: 檢查 IAM 是否有 Secret Manager Secret Accessor 權限;確認 ssh-keyscan 的 Host 是否正確。
Q4: 設定了 Cloud NAT 但外部 API 看到的 IP 依然不是固定 IP 原因: 流量路徑設定錯誤,未將「所有流量」導向 VPC。
解決: 前往 Cloud Run UI,確認 Egress 是否選取為 「所有流量 (All Traffic)」 而非「僅私有 IP」。
Q5: VPC 內部 API 連線逾時 (Timeout) 原因: VPC 防火牆規則未允許來自 Connector 的流量。
解決: 在防火牆規則中,新增一條「入站」規則,來源 IP 填入 VPC Connector 的子網路網段(例如 10.8.0.0/28),通訊協定允許對應的 API Port。
- 後續維護建議 監控: 建議啟用 Cloud Logging 查看 Cloud Run 的啟動日誌。
成本: VPC Connector 會產生固定的實例費用,若流量較小,可將實例數設定為 min: 2, max: 3 以節省成本。