你的儲存庫裡同時放著一個 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 時間會被拉得很長。兩個簡單有效的做法:
- 映像層快取落盤:不要每次
colima delete,只用colima stop/colima start,虛擬機器磁碟(預設在~/.colima)會保留已拉取的映像層,重啟後不用重新下載。 - 建置快取掛載卷:後端 Dockerfile 裡給
node_modules、vendor、.cargo等依賴目錄宣告具名 volume,配合docker compose的--wait,首次建置慢一點,後續增量建置能省下大半時間。
配合前面提到的 virtiofs 掛載,專案目錄的讀寫基本不會成為瓶頸,真正值得盯的是網路層——如果整合測試要存取外部 API,記得給測試環境單獨配 mock 或沙箱位址,不要讓 CI 悄悄打到生產介面。
踩坑清單與檢查項
實際接入過程裡容易栽的坑,按優先順序列一遍:
- 忘記切 docker context:裝了 Colima 之後如果之前用過 Docker Desktop,
docker命令可能還指向舊的 context,docker context use colima這一步不能省。 - VM 類型選錯:舊版 Colima 預設可能用
qemu,在 Apple Silicon 上一定要顯式指定--vm-type=vz,效能差距明顯。 - 磁碟無限增長:映像層不清理會一直占用
--disk參數設的空間,建議 CI 流程裡定期跑一次docker system prune -af --volumes。 - 多任務並行搶資源:如果同一台機器上還並行跑其他 Xcode 建置任務,Colima 的記憶體配置要相應下調,避免 OOM。
- 架構不匹配的映像:後端如果引用了只支援 x86_64 的基礎映像,在 Apple Silicon 上會走 QEMU 模擬層,速度驟降,盡量確認映像有原生
arm64版本。
把這套流程跑順之後,同一台雲端 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 憑證,配置隨時可升級。