Zeabur 搬到 Google Cloud Run:不用寫 Dockerfile,實際部署過的步驟

Zeabur 上「直接從 GitHub 部署、沒有 Dockerfile」的 Node、Python、Go 後端,可以用 gcloud run deploy --source 搬到 Cloud Run。我們實際部署過一次,連 Secret 權限錯誤的訊息與修法一起列出來。

重點

  • 沒有 Dockerfile 也能部署:加上 --source 參數部署時,會用 buildpacks 自動偵測語言。
  • 金鑰放 Secret Manager,用 --set-secrets 掛載;服務帳號要有 Secret Manager Secret Accessor 角色。
  • Cloud Run 的檔案系統是暫時的,上傳檔案要改存 Cloud Storage 或 R2。
  • 搬完記得到 LINE Developers 更新 Webhook URL。
這篇怎麼驗證的?(3 項實測、3 項依官方文件)
實際跑過
  • 沒有 Dockerfile 的 Node 服務,用 gcloud run deploy --source 部署到 asia-east1,網址可正常回應(測完已刪除)
  • --set-env-vars 設定環境變數、--set-secrets 掛載 Secret Manager 的值,程式可讀到
  • 服務帳號沒有 Secret 權限時的錯誤訊息,以及授權後重新部署成功
依官方文件撰寫、未實際操作
  • 全新 GCP 專案需要啟用哪些 API、授予哪些角色:我們是在既有專案上測試,這部分依 Google 官方文件撰寫
  • LINE Developers 後台的操作:依我們自己維運 LINE Bot 的經驗,未在本次測試中重做
  • 綁定自訂網域:未實測,請依 Google 官方文件
目錄(8 節)
  1. 適合誰
  2. 第 0 步:新專案的準備(依官方文件)
  3. 第 1 步:確認程式監聽 PORT
  4. 第 2 步:部署
  5. 第 3 步:金鑰用 Secret Manager,不要寫在環境變數
  6. 第 4 步:資料庫
  7. 第 5 步:LINE Bot 要改 Webhook 網址
  8. 第 6 步:綁自己的網域

適合誰

  • Zeabur 上從 GitHub 部署的後端:Node.js、Python、Go 的 API,或是 LINE Bot、Discord Bot
  • 流量不大,希望沒人使用時不收運算費(Cloud Run 會自動縮到 0)
  • 想要台灣機房:asia-east1 就在台灣

不適合:需要永久硬碟的服務(例如把上傳檔案存在本機資料夾)。Cloud Run 的檔案系統是暫時的,重新部署或縮到 0 之後,寫進去的檔案就不見了。這類服務請把檔案改存到 Cloud Storage 或 R2,或改用 VPS(見 n8n 篇)。

第 0 步:新專案的準備(依官方文件)

  1. 安裝 gcloud CLI,執行 gcloud init 登入並選擇專案。專案必須綁定帳單帳戶
  2. 啟用 API:
gcloud services enable run.googleapis.com cloudbuild.googleapis.com
  1. 從原始碼部署時,Cloud Build 預設使用 Compute Engine 的預設服務帳號,官方文件要求授予它 Cloud Run Builder 角色:
gcloud projects add-iam-policy-binding 你的專案ID \
  --member=serviceAccount:專案編號[email protected] \
  --role=roles/run.builder

文件提到,這個授權需要幾分鐘才會生效。

一定要確認目前用的是哪個專案。 每個 gcloud 指令都加上 --project=你的專案ID,或先執行 gcloud config get-value project 確認。我們自己的電腦上就有好幾個專案,預設專案常常不是要部署的那一個。

第 1 步:確認程式監聽 PORT

Zeabur 和 Cloud Run 都用 PORT 環境變數告訴程式要監聽哪個 port。如果你在 Zeabur 上已經照文件用 $PORT,這一步不用改。如果程式寫死 3000,要改成:

app.listen(process.env.PORT || 3000);

第 2 步:部署

在專案根目錄執行(不需要 Dockerfile,Google 的 buildpacks 會自動偵測語言):

gcloud run deploy my-api --source . --region asia-east1 \
  --allow-unauthenticated \
  --set-env-vars "NODE_ENV=production" \
  --project=你的專案ID

完成後會顯示 Service URL: https://my-api-xxxx.asia-east1.run.app。我們實測時,一個沒有 Dockerfile 的 Node 服務,第一次部署就成功回應。

如果專案根目錄有 Dockerfile,Cloud Run 會優先使用它。

第 3 步:金鑰用 Secret Manager,不要寫在環境變數

--set-env-vars 的值任何能看服務設定的人都看得到。資料庫密碼、API key 請放進 Secret Manager:

# 建立 secret(printf 不會在結尾多加換行)
printf '%s' 'postgresql://...' | gcloud secrets create database-url --data-file=- --project=你的專案ID

# 掛到服務上,程式一樣用 process.env.DATABASE_URL 讀取
gcloud run services update my-api --region asia-east1 \
  --set-secrets "DATABASE_URL=database-url:latest" --project=你的專案ID

實測會遇到的錯誤

服務帳號沒有讀取 Secret 的權限時,部署會失敗:

ERROR: (gcloud.run.deploy) ... Permission denied on secret: projects/.../secrets/database-url/versions/latest
for Revision service account [email protected]. The service account used must be granted
the 'Secret Manager Secret Accessor' role (roles/secretmanager.secretAccessor) at the secret, project or higher level.

修法是只針對這個 secret 授權(範圍最小),然後重新部署:

gcloud secrets add-iam-policy-binding database-url \
  --member="serviceAccount:錯誤訊息裡的服務帳號" \
  --role="roles/secretmanager.secretAccessor" --project=你的專案ID

我們實測:授權後重新部署,立刻成功。

第 4 步:資料庫

Cloud Run 不提供資料庫。PostgreSQL 可以搬到 Neon、Supabase 這類代管服務,或使用 Google 的 Cloud SQL。搬法見資料庫篇。

第 5 步:LINE Bot 要改 Webhook 網址

  1. 到 LINE Developers,選擇你的 Channel
  2. 「Messaging API」分頁 → Webhook URL,換成新的 Cloud Run 網址(加上你程式的路徑,例如 /webhook)
  3. 按「Verify」確認成功

Channel Secret 和 Access Token 也建議趁這次一起換新,見資安篇。

第 6 步:綁自己的網域

Cloud Run 綁自訂網域有好幾種方式(Cloud Run 網域對應、負載平衡器、Firebase Hosting),各有支援地區與費用上的差異,請依 Google 官方文件選擇。這一步我們這次沒有實測。 切換 DNS 的注意事項見網域與 DNS 篇。

常見問題

Zeabur 上沒有 Dockerfile 的專案可以部署到 Cloud Run 嗎?

可以。從原始碼部署(--source)時,若沒有 Dockerfile,會用 Google Cloud buildpacks 自動偵測語言並建置;我們用 Node.js 服務實測,第一次部署就成功。

Cloud Run 出現 Permission denied on secret 怎麼辦?

服務使用的服務帳號沒有讀取該 secret 的權限。授予它 roles/secretmanager.secretAccessor 角色(可以只針對該 secret)後重新部署即可。