🔄 用完即丟(Ephemeral)
每個 Job 都會啟動一台全新的 Runner VM。Job 結束後,VM 被銷毀,不留任何痕跡。
Runner 是 CI/CD 的核心引擎——每一個 Workflow Job 都在 Runner 上執行。本章深入探討 GitHub-hosted 與 Self-hosted Runner 的差異、Docker 容器化執行、快取與 Artifact 策略、除錯技巧,以及多種真實應用場景,幫助你從「能用」提升到「善用」。
CI/CD 的核心需求之一是隔離且可重現的執行環境。Runner 就是為此而生的——它提供一台全新的虛擬機器,讓你的程式碼在乾淨、獨立的環境中編譯、測試與部署。
每個 Job 都會啟動一台全新的 Runner VM。Job 結束後,VM 被銷毀,不留任何痕跡。
無殘留狀態代表沒有憑證外洩風險——前一個 Job 的 Token、密碼不會留給下一個 Job。
同樣的程式碼 + 同樣的 Runner Image = 同樣的結果。消除「在我的電腦可以跑」的問題。
從開發者推送程式碼到 Job 結束,Runner 經歷以下完整生命週期:
GitHub 提供的 hosted runner 預裝了大量開發工具,幾乎可以滿足所有常見的 CI/CD 需求。了解它們的能力與限制,有助於寫出更高效的 Workflow。
| 分類 | 預裝內容 |
|---|---|
| 程式語言 | Node.js、Python、Java、Go、Ruby、.NET、Rust、PHP、Swift |
| 套件管理 | npm、yarn、pip、Maven、Gradle、Bundler、Cargo |
| 建構工具 | CMake、Make、Autoconf、GCC、Clang |
| 容器工具 | Docker、Docker Compose、Podman(Linux) |
| 雲端 CLI | AWS CLI、Azure CLI、Google Cloud SDK |
| 瀏覽器 | Chrome、ChromeDriver、Firefox、Geckodriver |
| 資料庫 | SQLite、PostgreSQL client、MySQL client |
| 版本控制 | Git、Git LFS、SVN、Mercurial |
GitHub 每週更新 Runner Image,確保工具保持最新版本。ubuntu-latest 目前對應到 Ubuntu 22.04,未來會漸進切換到 24.04。如果需要固定版本,可使用 ubuntu-22.04 明確指定。
| 規格 | Standard Runner | Larger Runner(付費) |
|---|---|---|
| vCPU | 2 核心 | 2 / 4 / 8 / 16 / 32 / 64 核心 |
| 記憶體 | 7 GB | 8 – 256 GB |
| 磁碟空間 | 14 GB SSD | 最高 2,040 GB SSD |
| 作業系統 | Ubuntu、Windows、macOS | Ubuntu、Windows(macOS 另計) |
| GPU | ❌ 不支援 | ✅ 可選 GPU runner |
| 固定 IP | ❌ 動態 IP | ✅ 支援靜態 IP |
| 費用 | Public Repo 免費 | 依核心數按分鐘計費 |
Self-hosted Runner 讓你在自己的伺服器上執行 GitHub Actions Job。當 GitHub-hosted Runner 無法滿足需求時,這是最佳替代方案。
前往 Repo → Settings → Actions → Runners → New self-hosted runner,依平台選擇指令。
# 1. 建立目錄並下載
$ mkdir actions-runner && cd actions-runner
$ curl -o actions-runner-linux-x64.tar.gz -L \
https://github.com/actions/runner/releases/download/v2.x.x/actions-runner-linux-x64-2.x.x.tar.gz
$ tar xzf ./actions-runner-linux-x64.tar.gz
# 2. 設定(Token 由 GitHub 頁面提供)
$ ./config.sh --url https://github.com/YOUR_ORG/YOUR_REPO \
--token YOUR_TOKEN \
--labels linux,gpu,self-hosted
# 3. 安裝為系統服務(開機自動啟動)
$ sudo ./svc.sh install
$ sudo ./svc.sh start
$ sudo ./svc.sh status
# 1. 建立目錄並下載
$ mkdir actions-runner && cd actions-runner
$ curl -o actions-runner-osx-x64.tar.gz -L \
https://github.com/actions/runner/releases/download/v2.x.x/actions-runner-osx-x64-2.x.x.tar.gz
$ tar xzf ./actions-runner-osx-x64.tar.gz
# 2. 設定
$ ./config.sh --url https://github.com/YOUR_ORG/YOUR_REPO \
--token YOUR_TOKEN \
--labels macos,self-hosted
# 3. 安裝為 launchd 服務
$ ./svc.sh install
$ ./svc.sh start
# 1. 在 PowerShell 中下載並解壓縮
mkdir actions-runner; cd actions-runner
Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v2.x.x/actions-runner-win-x64-2.x.x.zip -OutFile actions-runner-win-x64.zip
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64.zip", "$PWD")
# 2. 設定
.\config.cmd --url https://github.com/YOUR_ORG/YOUR_REPO --token YOUR_TOKEN
# 3. 安裝為 Windows 服務
.\svc.cmd install
.\svc.cmd start
安裝時指定的 Label 就是 Workflow 中 runs-on 用來選擇 Runner 的依據:
# 在 Workflow 中指定 Self-hosted Runner
jobs:
train-model:
runs-on: [self-hosted, linux, gpu] # 需要同時符合三個 label
steps:
- uses: actions/checkout@v4
- run: python train.py
在組織 (Organization) 層級,可以用 Runner Group 將多台 Runner 分組管理,並指定哪些 Repo 可以使用:
Docker 是 Runner 上最強大的工具之一。你可以將整個 Job 跑在容器裡、啟動資料庫服務容器,甚至使用自製的 Docker Image。以下介紹三種常見的 Docker 使用模式。
根據需求選擇合適的容器化策略。
使用 container: 語法,將整個 Job 跑在指定的 Docker 容器中。好處是環境精確可控,且小型 Image 啟動更快。
name: Container Job 範例
on: push
jobs:
test:
runs-on: ubuntu-latest
container: node:20-slim # 整個 Job 跑在此容器中
steps:
- uses: actions/checkout@v4
- run: node --version # 使用容器內的 Node.js
- run: npm ci
- run: npm test
-slim 或 -alpine 版本的 Image 可以大幅減少下載時間。例如 node:20-slim 約 200 MB,而完整版約 1 GB。
Service Container 可以在 Job 旁邊啟動資料庫、快取等服務。服務名稱就是 hostname,無需額外設定。
name: Service Container 範例
on: push
jobs:
integration-test:
runs-on: ubuntu-latest
services:
postgres: # hostname = "postgres"
image: postgres:16
env:
POSTGRES_USER: testuser
POSTGRES_PASSWORD: testpass
POSTGRES_DB: testdb
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis: # hostname = "redis"
image: redis:7-alpine
ports:
- 6379:6379
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run test:integration
env:
DATABASE_URL: postgres://testuser:testpass@localhost:5432/testdb
REDIS_URL: redis://localhost:6379
將所有專案依賴預裝在自製 Image 中,大幅縮短每次 CI 的安裝時間。
步驟 1:撰寫 Dockerfile
# .docker/ci.Dockerfile
FROM node:20-slim
# 安裝系統依賴
RUN apt-get update && apt-get install -y \
python3 make g++ \
&& rm -rf /var/lib/apt/lists/*
# 預裝全域工具
RUN npm install -g typescript eslint
WORKDIR /app
步驟 2:在 Workflow 中使用
name: 使用自製 Image
on: push
jobs:
build:
runs-on: ubuntu-latest
container:
image: ghcr.io/my-org/ci-image:latest # 從 Container Registry 拉取
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
- run: npm ci # 系統依賴已預裝,安裝極快
- run: npm run build
- run: npm test
掌握快取、Artifact 與除錯技巧,能讓你的 Workflow 更快、更穩定、更容易排錯。
每一項都能顯著提升 CI/CD 體驗。
快取機制可以在不同 Workflow Run 之間保留依賴套件,避免每次都重新下載。核心概念是 Cache Key——用 lock 檔案的 hash 作為 key,當依賴沒變時直接恢復快取。
name: 使用快取
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# 快取 node_modules
- uses: actions/cache@v4
id: npm-cache
with:
path: node_modules
key: node-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
node-${{ runner.os }}-
# 只有 cache miss 時才安裝
- if: steps.npm-cache.outputs.cache-hit != 'true'
run: npm ci
- run: npm test
| 情境 | 行為 | 效果 |
|---|---|---|
| Cache Hit ✅ | 直接恢復快取,跳過 npm ci | 節省 30-120 秒 |
| Partial Hit 🔶 | 使用 restore-keys 恢復舊快取,再安裝差異 | 節省部分時間 |
| Cache Miss ❌ | 完整安裝,執行結束後自動儲存快取 | 下次會命中 |
Artifact 用於在不同 Job 之間傳遞檔案,或保存建置產物供事後下載。
name: Artifact 跨 Job 傳遞
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
# 上傳建置產物
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
retention-days: 7 # 保留 7 天
deploy:
needs: build # 等 build 完成才執行
runs-on: ubuntu-latest
steps:
# 下載前一個 Job 的產物
- uses: actions/download-artifact@v4
with:
name: build-output
path: dist/
- run: echo "部署 dist/ 內容到伺服器..."
Workflow 出問題時,以下技巧能幫你快速定位問題:
① 啟用 Step Debug Logging
# 在 Repo → Settings → Secrets → Actions 中新增:
# Name: ACTIONS_STEP_DEBUG
# Value: true
# 重新執行 Workflow,每個 Step 會顯示詳細的除錯資訊。
② SSH 進入 Runner 互動除錯
# 在 Workflow 中加入此 Step,執行時會暫停並提供 SSH 連線
- name: 互動除錯(SSH)
uses: mxschmitt/action-tmate@v2
if: failure() # 只在失敗時啟動
with:
limit-access-to-actor: true # 僅允許觸發者連線
③ 寫入 Step Summary
# 用 $GITHUB_STEP_SUMMARY 在 Actions 頁面顯示自訂 Markdown 摘要
- name: 產生測試報告摘要
run: |
echo "## 🧪 測試結果" >> $GITHUB_STEP_SUMMARY
echo "| 類別 | 通過 | 失敗 |" >> $GITHUB_STEP_SUMMARY
echo "|------|------|------|" >> $GITHUB_STEP_SUMMARY
echo "| 單元測試 | 42 | 0 |" >> $GITHUB_STEP_SUMMARY
echo "| 整合測試 | 18 | 1 |" >> $GITHUB_STEP_SUMMARY
Matrix 可以平行測試多個環境組合,搭配進階參數讓策略更靈活:
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false # 一個失敗不會取消其他 Job
max-parallel: 4 # 最多同時跑 4 個 Job
matrix:
node: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
exclude:
- node: 18 # 排除 Node 18 + Windows 組合
os: windows-latest
include:
- node: 22 # 額外加入 Node 22 + macOS 組合
os: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci && npm test
| 參數 | 說明 | 預設值 |
|---|---|---|
fail-fast | 一個 Job 失敗時是否取消其他正在執行的 Job | true |
max-parallel | 同時執行的 Job 最大數量 | 無限制 |
include | 在 matrix 組合外額外加入特定組合 | - |
exclude | 從 matrix 組合中排除特定組合 | - |
以下列出六種常見的 Runner 應用場景,涵蓋前端、後端、教學、文件、行動 App 與機器學習領域。
自動跑 Lint + 單元測試,通過後自動部署到 GitHub Pages 或 Vercel。搭配快取加速 node_modules 安裝。
使用 Service Container 啟動 PostgreSQL / Redis,執行整合測試,通過後建構 Docker Image 並推送到 AWS ECR / GCP Artifact Registry。
配合 GitHub Classroom,學生 push 作業後自動執行測試腳本,即時回饋評分結果。老師可透過 Actions 記錄追蹤每位學生的提交。
將 Markdown 原始碼自動轉換為精美網站。支援 MkDocs、VitePress、Jekyll 等靜態網站生成器,push 即自動部署。
在 macOS runner 上建構 iOS App(使用 Xcode),在 Linux runner 上建構 Android App(使用 Gradle)。搭配 Fastlane 自動化發布到 App Store / Google Play。
在 Self-hosted GPU Runner 上訓練模型。將訓練結果作為 Artifact 上傳,並自動產生模型指標的 Step Summary 報告。
container: node:20-slim。npm ci 與 npm test。node:20-alpine,比較啟動時間差異。services.postgres 區塊。POSTGRES_USER、POSTGRES_PASSWORD、POSTGRES_DB。localhost:5432 連線到 PostgreSQL。npm ci 步驟的執行時間。actions/cache@v4,使用 package-lock.json 的 hash 作為 key。ACTIONS_STEP_DEBUG = true。$GITHUB_STEP_SUMMARY 輸出自訂摘要。fail-fast、include、exclude、max-parallel 微調。container: 語法將 Job 跑在 Docker 容器中。actions/cache 快取策略,顯著加速 Workflow。