iT邦幫忙

2025 iThome 鐵人賽

DAY 22
0

前言

今天來點輕鬆的,因為之後我想要實際把專案部署到雲端上,所以想要寫一個 GitHub Actions 的 CI/CD 流程,今天就從最簡單的步驟開始,目標是在專案目錄下寫好一個最簡易的 Dockerfile 跟 GitHub Workflow 的腳本,成果是要在 Merge 到 release 分支時觸發這個 flow,把專案打包成 Docker Image 後推到 GCP 上的 Artifact Registry 就算完成。

實作:GitHub Actions & Docker Build

今天實作的步驟是:

  1. 寫好 Dockerfile
  2. 寫好 GitHub Workflow
  3. 在 Remote Repo Setting 裡配好環境變數
  4. 發 pr 給 release & merge
  5. 跑 GitHub Actions
  6. 去看 GCP 的 Artifact Registry

Dockerfile:附帶逐行說明

# 指定容器要用的 jdk 版本
FROM eclipse-temurin:21-jdk-alpine

# 設定容器內的工作目錄為 /app。之後所有的操作都會在這個目錄下執行。
WORKDIR /app

# 複製 Maven Wrapper 執行檔到容器的當前目錄。這允許在沒有預安裝 Maven 的環境中執行 Maven 指令。
COPY mvnw .

# 複製 Maven Wrapper 的設定資料夾到容器中。這包含了 Maven Wrapper 運行所需的設定檔案和 JAR 檔。
COPY .mvn .mvn

# 複製 Maven 專案的設定檔 pom.xml 到容器中。此檔案包含專案依賴、建置設定等重要資訊。
COPY pom.xml .

# 為 Maven Wrapper 檔案添加執行權限。在 Linux 系統中,檔案需要執行權限才能被執行。
RUN chmod +x ./mvnw

# 預先下載所有專案依賴到本地倉庫。-B 參數表示批次模式,避免互動式輸入。
RUN ./mvnw dependency:go-offline -B

# 複製應用程式的源代碼資料夾到容器中。這包含了所有 Java 類別檔案和資源檔案。
COPY src ./src

# 執行 Maven 建置指令,清理並打包應用程式為 JAR 檔。-DskipTests 參數跳過單元測試以加快建置速度。
RUN ./mvnw clean package -DskipTests

# 聲明容器會使用 8080 端口。這是一個文件化的聲明,實際的端口對應需要在運行時指定。
EXPOSE 8080

# 設定容器啟動時的預設指令。執行打包好的 JAR 檔案來啟動 Spring Boot 應用程式。
CMD ["java", "-jar", "target/playground-module-0.0.1-SNAPSHOT.jar"]

GitHub Workflow

GitHub Actions 工作流程,用於自動部署 Docker Image 到 GCP 的 Artifact Registry,主要對 jobs 說明一下,這是實際的部署流程:

  1. Checkout 使用 GitHub 官方 action 來下載當前分支的程式碼。讓後續步驟可以存取專案檔案和 Dockerfile。
  2. Google Auth 使用 Google 官方 action 進行 GCP Service Account 認證。透過在 GitHub Secrets 中的 Service Account 金鑰來取得存取權限。
  3. Set up Cloud SDK 安裝並設定 Google Cloud SDK 工具。這提供了 gcloud 命令列工具,用於與 GCP 服務互動。
  4. Configure Docker to use gcloud 設定 Docker 使用 gcloud 的認證來存取 GCP Artifact Registry。--quiet 參數避免互動式確認提示。
  5. Build and Push Docker image 建置 Docker Image 後推到 Registry。Image 標籤使用 Git commit SHA 來確保唯一性,便於追蹤和 rollback。
name: Deploy to GCP Artifact Registry

on:
  push:
    branches: [ release ]
  pull_request:
    branches: [ release ]
    types: [ closed ]

env:
  PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
  GAR_LOCATION: ${{ secrets.GCP_REGION }}
  REPOSITORY: ${{ secrets.ARTIFACT_REPO }}
  SERVICE: ${{ secrets.SERVICE }}

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Google Auth
        uses: google-github-actions/auth@v2
        with:
          credentials_json: '${{ secrets.GCP_SA_KEY }}'

      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v2

      - name: Configure Docker to use gcloud
        run: gcloud auth configure-docker $GAR_LOCATION-docker.pkg.dev --quiet

      - name: Build and Push Docker image
        run: |
          docker build -t $GAR_LOCATION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$SERVICE:$GITHUB_SHA .
          docker push $GAR_LOCATION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$SERVICE:$GITHUB_SHA

Setting:GitHub Secrets

剛剛提到的「透過在 GitHub Secrets 中的 Service Account 金鑰來取得存取權限」,等於是在 GitHub 的 Repository 設置環境變數的概念,這邊就是用到配在 GitHub Secrets 的環境變數:

env:
  PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
  GAR_LOCATION: ${{ secrets.GCP_REGION }}
  REPOSITORY: ${{ secrets.ARTIFACT_REPO }}
  SERVICE: ${{ secrets.SERVICE }}

實際上要去哪配呢?先到遠端倉庫找到 Setting 齒輪:

https://ithelp.ithome.com.tw/upload/images/20250912/201615825eQfwdNmHq.png

然後找到 Secrets 開頭的 Tab 後點開找到 Actions,就可以看到配置環境變數的地方了,要配的有 GCP 相關的參數等等,這邊就不贅述:

https://ithelp.ithome.com.tw/upload/images/20250912/20161582Wza0zlzf3n.png

GitHub Actions

假設現在我們已經在本地 commit 後 push 到了遠端,也發了 PR 給 release 分支,merge 進來後觸發了 GitHub Actions,也就是 GitHub 的 CI/CD 流程,我們可以點開 Actions 這個 Tab 進去看看我們的 jobs 有沒有順利進行:

https://ithelp.ithome.com.tw/upload/images/20250912/20161582AQHwrSC7oS.png

再點進去看看:非常好!這裡的 jobs 就對應了剛剛 workflow .yaml 定義的 jobs,看起來都有跑完成功。

https://ithelp.ithome.com.tw/upload/images/20250912/20161582gbU6qYjDL4.png

Artifact Registry

實際去 GCP 的 Artifact Registry 驗收也成功,太順利了!

https://ithelp.ithome.com.tw/upload/images/20250912/20161582BfWfiKjZQF.png

總結

今天非常開心又體驗了一次天靈蓋酥酥麻麻的感覺,算是一次就把我的 Image 給推上雲端的倉庫,其實是得益於好幾個月前就已經把那些金鑰之類的就配好,不然要搜集這些資訊也是蠻頭痛,總之看到 jobs 都有順利跑過真的蠻爽的,明天繼續努力。


上一篇
Day 21 | 第三階段系統優化 | ObjectMapper 單例
下一篇
Day 23 | 第三階段系統優化 | GitHub Actions + GCP 部署血淚史:踩雷大會
系列文
系統設計一招一式:最基本的功練到爛熟就是殺手鐧,從單體架構到分布式系統的 Lab 實作筆記25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言