iT邦幫忙

1

GitHub Action 教學:把 Docker 容器自動部署到 Cloud Run

  • 分享至 

  • xImage
  •  

banner

每次上傳新的 Docker Image 到 Google Cloud Run 時,都要另外打 gcloud 指令實在是有點繁瑣,本篇會與你分享筆者怎麼使用 GitHub Action,設定 Docker 自動容器話與 Cloud Run 的自動部署,不用再打部署指令,簡化開發流程!

本文同時發佈於我的個人部落格


前情提要

這是筆者第一篇程式的技術學習筆記,所以在解釋跟教學步驟上會略顯繁瑣、或是有需改善的地方,還請大佬或是讀者不吝指教。

而筆者也將本文章的難度設定成入門門檻,所以會含括一些前置步驟的教學,如果你已經設定過可以直接略過!

Cloud Run + GitHub Action:省去手動部署的流程

GitHub Action 是 Github 的 CI 功能,簡而言之就是把 commit 後的 Build、Test、Deploy 的流程全都自動化,不用手動另外執行( 就是做 Jenkins 的工作 )

github action PPAP

這位前輩的文章有更完整的解釋:GitHub Actions 基本介紹 - 開始自動化 workflow 的第一步 - iT 邦幫忙

那麽 GitHub Action 對於要部署到 Cloud Run 的專案有什麼好處呢?透過設定 GitHub Action,你可以將這些過程全都自動化:

  1. 完成Google Cloud & Docker 登入驗證
  2. 建立程式的 Docker 容器
  3. 提交 Docker 容器到 Artifact Registry
  4. 將容器部署到 Cloud Run 服務

而且是在每次新的 commit 後就會自動完成,你只需專注做程式碼的開發即可,是不是超方便的?

不過補充一下,GitHub Actions 是有額度限制的,超過額度後要付費才能繼續用,以下是 GitHub Action 的免費使用額度,收費標準以執行時間為單位:

  • GitHub 免費版:每個月 2,000 分鐘
  • GitHub Pro:每個月 3,000 分鐘
  • GitHub 公開 Repo: 不限次數免費使用

開始之前,你應該要先 …

但在進到教學正文之前,會需要你先做以下三件事:

  1. 略懂 Docker 跟 GCP Cloud Run 的用途
  2. 寫好專案的 Dockerfile
  3. 在 GCP 建立好自己的專案,並取得專案編號

如果做好前置作業,就照著下文設定你的 GitHub Action 吧!整個過程大約花費 10 分鐘。


步驟一:設定 Google Cloud 專案的 Identity federation

本篇文章會教學用 Google 官方的 YAML,而針對 Auth 部分,會需要用到專案的 Workload Identity Federation 來進行 GitHub Action 的 OIDC 驗證,因此,這段會先教學如何建立 GCP 專案的 Identity federation。

下文會用 gcloud 指令進行操作,如果你的電腦還沒有裝 Google Cloud SDK,或之前都是用 GUI 網頁來部署的話,可以照著這篇文章的教學安裝 SDK 並完成設定:

如何安裝 Google Cloud SDK 命令行工具?macOS 就是那麼簡單 - Python 編程.圖表

// 雖然上篇文章是 MacOS 版本的,但安裝過程跟 Windows 類似~

安裝好 SDK 並登入管理 GCP 的 Google 帳號後,打開 Terminal 先設定一個環境變數,省去重複打編號的過程:

export PROJECT_ID="你的專案 ID"

接著創建一個服務帳戶,你可以自訂第一個引號的帳戶 ID:

( 如果你已經有一個 GCP 專案服務帳戶,可以略過這步,並記下你現有專案服務帳戶的 email 位置 )

gcloud iam service-accounts create "github-service-account" \
  --project "${PROJECT_ID}"

// 如果你的 Cloud Run 專案會需要使用其他 Google Cloud 的資源( 像是 Cloud Storage、Cloud SQL )記得為服務帳戶新增相對應的權限,你可以用 gcloud 指令或是到 GCP 網頁版→ IAM 與管理內新增權限。

再來新增一個 Workload Identity 集區( Workload Identity Pool )你可以自訂 “github-pool” 跟 display-name 的名稱:

gcloud iam workload-identity-pools create "github-pool"
  --project="${PROJECT_ID}" \
  --location="global" \
  --display-name="GitHub Deployment Poll"

接著輸入這段指令取得集區的編號:

gcloud iam workload-identity-pools describe "github-pool"
  --project="${PROJECT_ID}" \
  --location="global" \
  --format="value(name)"

輸出會像這樣 projects/111111111/locations/global/workloadIdentityPools/my-pool,將這組集區編號設定成環境變數,方便等等重複使用:

export WORKLOAD_IDENTITY_POOL_ID="..."

接著為集區新增一個 Provider:

gcloud iam workload-identity-pools providers create-oidc "github-provider" \
  --project="${PROJECT_ID}" \
  --location="global" \
  --workload-identity-pool="github-pool" \
  --display-name="Github Provider" \
  --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \
  --issuer-uri="https://token.actions.githubusercontent.com"

p.s. 如果你要建立全部 repo 權限的 Provider,attribute-mapping 要改成這個:

--attribute-mapping="google.subject=assertion.sub,attribute.repository_owner=assertion.repository_owner"

再來為服務帳號綁定工作集區的使用者 IAM 權限,先設定一個環境變數,設定成你的 GitHub Repo 名稱:

export REPO="github_username/repo_name"

再打這段指令:

gcloud iam service-accounts add-iam-policy-binding "github-service-account@${PROJECT_ID}.iam.gserviceaccount.com" \
  --project="${PROJECT_ID}" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_ID}/attribute.repository/${REPO}"

如果你要套用於全部 repo 的 GitHub Action,先設定一個 OWNER 環境變數:

export OWNER="username"

再修改前兩個的指令的 member 參數內容:

--member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_ID}/attribute.repository_owner/${OWNER}"

最後輸入以下指令,拿到集區 Provider 的資源名稱並記下來:

gcloud iam workload-identity-pools providers describe "my-provider" \
  --project="${PROJECT_ID}" \
  --location="global" \
  --workload-identity-pool="my-pool" \
  --format="value(name)"

你應該會得到類似以下的名稱,稍後新增 repo secret 時會用到:

projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider

步驟二:設定 GitHub Repo Secret

由於上文設定的 Google Cloud 資源名稱跟服務帳戶都是機密資訊,無論 repo 是否為 public 還是 private,都不建議直接寫在 GitHub Action 的 YAML 檔上面。

而針對不想公開在網路上,但又需要用在 GitHub Action 內的敏感資訊( 像是 GCP 集區名稱、密鑰、資料庫網址 )可以設定成 repo 的 secret,讓 GitHub Action 可以用類似環境變數的方式存取,同時讓敏感資訊不會直接暴露在 YAML 上。

所以接下來要新增 Cloud Run 自動部署所需的 secret。先打開你的 GitHub Repository 頁面,進入 Setting,點選左側選單 Secrets and variables → Action:

github action 設定 secret

點選 New repository secret,新增兩個 secret:

  1. WIF_PROVIDER : 步驟一最後取得的資源名稱
  2. WIF_SERVICE_ACCOUNT : 步驟一設定的服務帳戶( 包含 @ 之後的網域 )


步驟三:建立 Cloud Run GitHub Action

最後,我們就能沿用 Google 官方寫好的 Cloud Run Deploy YAML 檔到 repo 內,回到你的 repo 頁面 → Actions:

搜尋 Cloud Run,並點選 “Build and Deploy to Cloud Run” :

接著,修改 51 ~ 55 行的環境變數,根據註解自訂成你的專案編號、Cloud Run 服務名稱跟地區,地區可以使用 asia-east1 也就是台灣的機房:

另外記得要稍微改一下 109 行的 Docker image 網址,改成:

image: ${{ env.GAR_LOCATION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.SERVICE }}/${{ env.SERVICE }}:${{ github.sha }}

// p.s. 筆者用官方的 YAML 部署時,就遇到了 image 網址少了一個 image name 參數的錯誤,上面的解法是參考這篇的討論:

Docker push "Missing image name"-error when pushing to GCP Artifact Registry from Github Actions

完成所有修改後,按右上方的 Commit change、新增 GitHub Action 的 YAML 檔就大功告成:

之後每次 commit 到 repo 的 main 分支就會自動執行 GutHub Action,將程式打包成 Docker image 並部署到 Cloud Run上了:


總結 Wrap up

以上就是設定 Cloud Run 自動部署的 GitHub Action 操作教學了,再重新概述一下三個步驟:

  1. 設定 GCP 專案的 Identity federation
  2. 將集區的 Provider 名稱和服務帳戶新增到 Repo Action 的 secret
  3. 建立並自訂 GitHub Action YAML 檔案

透過以上三步,就能設定 Repo 的 Action 了,你也可以另外加入測試等其他步驟,完善你的 CI/CD 流程,不過使用時要注意 GitHub Action 的額度限制喔。

筆者會有寫這篇教學的靈感,是因為趁暑假自學 Web 開發的技術時,剛好碰到 Serverless 的部署,我希望能自動化 Cloud Run 部署的工作,也趁機學一下 GitHub Action 的原理跟實作,只是網路上的文章都是舊版的部署方法,便記錄新版 Google 官方的 Cloud Run Action 怎麼設定。

當然,筆者在這篇是直接用 Google 官方寫的 YAML 檔,也沒有加入 Unit test 等項目,所以沒有發揮用 Actions 做 CI/CD 的功能,未來若有機會進一步學到這塊的話,會再撰寫文章跟大家分享我的淺見所學。

希望這篇文章有幫到你的開發!

本文同時發佈於我的個人部落格

Reference

本篇教學主要是受到下文的啟發,感謝 Robby 前輩寫的筆記文:

GCP - 使用 Github Actions 部署 React 到 Cloud Run | Robby - 全端的 Front-End Engineer - 點部落

GitHub - google-github-actions/auth: A GitHub Action for authenticating to Google Cloud.


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言