あなたのリポジトリには iOS アプリとそのバックエンドサービスが同居している——バックエンドは docker-compose でデータベース、メッセージキュー、いくつかのマイクロサービスを立ち上げ、統合テストは実際にこれらのコンテナに接続できてこそ動く。iOS 側は HireVPS のクラウド Mac mini を借りて Xcode ビルドをしており、ここまでは順調だった。ところが CI で同じマシン上にバックエンドの統合テストもついでに走らせようとした途端、Apple Silicon にはネイティブの Linux カーネルがなく、docker run はデーモンが見つからないと即座にエラーを返すことに気づく。これは設定の問題ではなく、アーキテクチャの問題だ——Docker は macOS 上では最初から「間借り」で動いているのである。
シナリオ:クラウド Mac でも Linux コンテナを動かす理由
monorepo はますます一般的になり、1 つの PR で iOS クライアントとバックエンドの API を同時に変更することも多い。iOS 側だけをテストしていては、プロトコルの不整合を発見できない。理想的なパイプラインはこうだ:同じ runner 上で、まず Xcode でビルドしてユニットテストを走らせ、続いて docker-compose で定義したバックエンドの依存を立ち上げ、統合テストを一巡させ、最後に結果をまとめて報告する。このやり方の利点は明快だ——CI 環境を二重に維持する必要がなく、マシン間通信のためにネットワークポリシーに穴を開ける必要もない。前提となるのは、そのクラウド Mac が Linux コンテナを動かせることだ。
Apple Silicon にはネイティブの Linux カーネルが存在しないため、「Docker を動かす」あらゆる方法は本質的に、まず隠れた Linux 仮想マシンを起動することに帰着する——パフォーマンスの良し悪しは、この VM にどれだけの CPU とメモリを割り当てるかにほぼ左右される。
準備:軽量な仮想化方式を選ぶ
macOS でコンテナを動かす主な選択肢は二つ——Docker Desktop と Colima(ネイティブの docker CLI と組み合わせる)だ。両者ともベースは Apple の Virtualization.framework を使って軽量な Linux VM を起動する点で同じだが、形態と適した用途が異なる。
Docker Desktop と Colima の選び方
| 観点 | Docker Desktop | Colima |
|---|---|---|
| 操作形態 | GUI + バックグラウンドデーモン | CLI のみ |
| 起動方式 | 手動またはログイン時に自動起動 | スクリプトからワンコマンドで起動 |
| リソース消費 | 高め、複数プロセスが常駐 | 軽量、必要な時だけ起動・停止 |
| 向いている場面 | ローカルでの日常的なデバッグ | 無人運用の CI runner |
| ライセンス制限 | 企業規模では有料ライセンスが必要 | オープンソース・無料 |
無人運用の runner で動く CI にとって、Colima は明らかに向いている。GUI セッションに依存せず、シェルスクリプトの中でワンコマンドで起動し、終わればすぐ止められる。孤立プロセスがメモリを占有し続けることもない。
インストールとリソース割り当て
クラウド 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 の VM にはホストメモリの 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() のステップが重要だ。テストが失敗してもコンテナと VM は必ず停止させる必要がある。そうしないと、長期契約のクラウド Mac 上に孤立した VM がどんどん積み重なり、メモリを占有して次のビルドを遅くしてしまう。
キャッシュ戦略:イメージレイヤーと依存関係の再利用
Colima の VM を再起動するたびにイメージを再取得し、依存関係を再インストールしていると、CI の所要時間がどんどん延びてしまう。効果的でシンプルな方法が二つある:
- イメージレイヤーをディスクに保持する:毎回
colima deleteするのではなく、colima stop/colima startだけを使う。VM のディスク(デフォルトでは~/.colima)には取得済みのイメージレイヤーが保持され、再起動時に再ダウンロードは不要になる。 - ビルドキャッシュ用のボリュームをマウントする:バックエンドの Dockerfile で
node_modules、vendor、.cargoなどの依存ディレクトリに名前付きボリュームを宣言し、docker composeの--waitと組み合わせる。初回ビルドは少し遅くなるが、以降の差分ビルドでは大幅な時間短縮になる。
前述の virtiofs マウントと合わせれば、プロジェクトディレクトリの読み書きはほぼボトルネックにならない。本当に注視すべきはネットワーク層だ——統合テストが外部 API にアクセスする場合は、テスト環境専用のモックやサンドボックスのアドレスを用意し、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 を提出すれば 1 本のパイプラインで完全な成功/失敗の判定が得られるようになる。
よくある質問
Apple Silicon のクラウド Mac は Docker をネイティブに動かせますか?
動かせません。Docker Desktop も Colima も Virtualization.framework を使って隠れた Linux 仮想マシンを起動し、コンテナはその中で動きます。性能は割り当てた CPU とメモリ次第です。
CI に組み込むなら Colima と Docker Desktop どちらが良いですか?
CI では Colima を推奨します。CLI ツールでリソース消費が少なく起動も速く、runner 内でスクリプトから自動起動しやすいためです。Docker Desktop はローカル GUI での日常デバッグに向いています。
メモリ容量が違うプランで Colima のリソース配分はどうすべきですか?
目安としてホストメモリの 50%〜70% を Colima の VM に割り当てます。例えば 32GB のホストなら 12GB・4 コアが目安です。実際の構成は控制台で現在選べる構成を確認し、負荷テストで調整してください。
HireVPS(HireVPS)
今すぐ専有クラウド Mac mini を試してみましょう
日単位でレンタル可能、2分で SSH/VNC の認証情報を取得、プランはいつでもアップグレードできます。