雲端 Mac 上跑 Linux 容器:打通 iOS 與後端混合 CI 流水線

CI/CD 實踐 ·約 7 分鐘閱讀

雲端 Mac 上跑 Linux 容器:打通 iOS 與後端混合 CI 流水線

你的儲存庫裡同時放著一個 iOS App 和它的後端服務:後端用 docker-compose 拉起資料庫、訊息佇列和幾個微服務,整合測試得真的連上這些容器才能跑。iOS 那邊租了一台 HireVPS 的雲端 Mac mini 做 Xcode 建置,一切都很順利,直到你想讓 CI 在同一台機器上順手跑一輪後端整合測試——才發現 Apple Silicon 上沒有原生 Linux 核心,docker run 直接報錯找不到守護程序。這不是設定問題,是架構問題:Docker 在 macOS 上從來就是「借殼」執行的。

場景:為什麼在雲端 Mac 上也要跑 Linux 容器

monorepo 越來越常見,一次 PR 可能同時改動 iOS 客戶端和後端介面,只測 iOS 側根本發現不了協定不匹配的問題。理想的流水線是:同一台 runner 上,先用 Xcode 建置並跑單元測試,再拉起 docker-compose 定義的後端依賴,跑一輪端到端整合測試,最後統一回報結果。這樣做的好處很直接——不用維護兩套 CI 環境,也不用在網路政策上為跨機器通訊開洞。前提是這台雲端 Mac 得能跑 Linux 容器。

Apple Silicon 上沒有原生的 Linux 核心,任何「跑 Docker」方案本質上都是先啟動一台隱藏的 Linux 虛擬機器——效能好壞幾乎全看這台虛擬機器分到多少 CPU 和記憶體。

準備工作:選一套輕量虛擬化方案

macOS 上能跑容器的路子主要兩條:Docker Desktop 和 Colima(搭配原生 docker CLI)。兩者底層都基於 Apple 的 Virtualization.framework 啟動一台精簡 Linux VM,差別在形態和適用場景。

Docker Desktop 與 Colima 的取捨

維度 Docker Desktop Colima
互動形式 圖形介面 + 背景守護程式 純命令列
啟動方式 手動或登入時自動啟動 腳本一條命令拉起
資源占用 較高,常駐多個程序 輕量,按需啟停
適合場景 本機日常除錯 無人值守的 CI runner
授權限制 企業規模需付費授權 開源免費

對跑在無人值守 runner 裡的 CI 來說,Colima 明顯更合適:它不依賴圖形工作階段,可以在 shell 腳本裡一條命令拉起、跑完就關,不會有孤兒行程占著記憶體。

安裝與資源配置

在雲端 Mac mini 上,先用 Homebrew 裝好工具鏈:

brew install colima docker docker-compose docker-buildx

colima start \
  --cpu 4 \
  --memory 12 \
  --disk 60 \
  --vm-type=vz \
  --mount-type=virtiofs

docker context use colima
docker compose -f docker-compose.ci.yml up -d --wait

--vm-type=vz 用的是 Apple 原生虛擬化後端(比早期的 QEMU 模式快不少),--mount-type=virtiofs 讓容器掛載的專案目錄讀寫效能接近本機磁碟,這兩個參數不加的話,建置速度和檔案 I/O 都會明顯打折。

資源配置沒有萬能公式,但有個經驗起點:給 Colima 的虛擬機器留主機記憶體的 50%~70%,CPU 核心數留一半左右給 Xcode 建置用。按機型記憶體對照,大致可以這樣起步(具體以主控台確認當前可選規格為準):

機型記憶體 Colima 建議記憶體 Colima 建議 CPU
16GB 6GB 2 核
32GB 12GB 4 核
48GB 20GB 6 核
64GB 28GB 8 核

如果 Xcode 建置和 Colima 同時跑,記憶體配置過高會讓兩邊互相搶占導致 swap,建置時間反而變長——這個平衡點值得在正式接入 CI 前用一次完整流水線跑幾遍來校準。

接入 CI:讓 self-hosted runner 認得 Linux 容器

如果 runner 是 GitHub Actions self-hosted 類型,在 job 裡加一步啟動 Colima、跑完測試再清理即可,不需要額外的服務容器宣告:

jobs:
  hybrid-ci:
    runs-on: [self-hosted, macos, cloud-mac]
    steps:
      - uses: actions/checkout@v4
      - name: Xcode build & unit test
        run: |
          xcodebuild -scheme App -destination "platform=iOS Simulator,name=iPhone 15" test
      - name: Bring up backend containers
        run: |
          colima start --cpu 4 --memory 12 --vm-type=vz --mount-type=virtiofs
          docker compose -f docker-compose.ci.yml up -d --wait
      - name: Integration tests
        run: ./scripts/run-integration-tests.sh
      - name: Teardown
        if: always()
        run: |
          docker compose -f docker-compose.ci.yml down -v
          colima stop

if: always() 那一步很關鍵:即便測試失敗也要把容器和虛擬機器關掉,不然長租的雲端 Mac 上會越積越多孤兒虛擬機器,占著記憶體拖慢下一次建置。

快取策略:映像層與依賴複用

Colima 虛擬機器重啟後,如果每次都重新拉映像、重新裝依賴,CI 時間會被拉得很長。兩個簡單有效的做法:

  1. 映像層快取落盤:不要每次 colima delete,只用 colima stop/colima start,虛擬機器磁碟(預設在 ~/.colima)會保留已拉取的映像層,重啟後不用重新下載。
  2. 建置快取掛載卷:後端 Dockerfile 裡給 node_modulesvendor.cargo 等依賴目錄宣告具名 volume,配合 docker compose--wait,首次建置慢一點,後續增量建置能省下大半時間。

配合前面提到的 virtiofs 掛載,專案目錄的讀寫基本不會成為瓶頸,真正值得盯的是網路層——如果整合測試要存取外部 API,記得給測試環境單獨配 mock 或沙箱位址,不要讓 CI 悄悄打到生產介面。

踩坑清單與檢查項

實際接入過程裡容易栽的坑,按優先順序列一遍:

把這套流程跑順之後,同一台雲端 Mac mini 就能同時扮演 iOS 建置機和後端整合測試環境,不用再為跨機器協調網路和憑證操心,PR 送出後一條流水線就能給出完整的通過/失敗訊號。

常見問題

Apple Silicon 的雲端 Mac 能直接跑 Docker 嗎?

不能原生跑,Docker Desktop、Colima 等方案本質上都是先啟動一台隱藏的 Linux 虛擬機(基於 Virtualization.framework),容器實際跑在裡面,所以效能取決於分給虛擬機的 CPU 與記憶體。

Colima 和 Docker Desktop 該選哪個接入 CI?

CI 場景優先選 Colima:它是命令列工具,資源占用小、啟動快,適合以腳本方式在 runner 裡自動拉起;Docker Desktop 更適合本機圖形介面日常除錯,不建議裝在無人值守的 runner 上。

機型記憶體不同,Colima 該怎麼分配資源?

通常給 Colima 虛擬機留主機記憶體的 50%~70%,例如 32GB 記憶體的機型可以分給 Colima 12GB、4 核,實際配置以控制台確認當前可選配置後再壓測調整為準。

HireVPS

今天就試試獨享雲端 Mac mini

按日起租,2 分鐘取得 SSH/VNC 憑證,配置隨時可升級。

立即租用 Mac mini