act + OrbStack でローカルCI環境を作る 2026 — GitHub Actions をMacで完全再現する
actとOrbStackを組み合わせてGitHub Actionsをローカル実行する方法を解説。Docker socketの設定・シークレット管理・ランナー選択・Claude Code連携まで、Mac上でCIを完全再現するための実践ガイド。
エンジニアのゆとです。
「GitHub Actionsのワークフローを直してPushしたら、CIで落ちた。ローカルでは動いてたのに」という経験は、開発者なら一度は通る道だ。
問題の構造は単純で、ローカルとCI環境が違う。ランナーのOSバージョン、環境変数の有無、Dockerの設定、パスの差異。これらが重なってCIだけ落ちる状態が生まれる。
act はGitHub Actionsのワークフローをローカルで実行するツールで、OrbStackと組み合わせるとMacでGitHub Actionsをほぼそのまま再現できる。Push前にCIが通るかどうか確認できる環境が手に入る。
actとは何か
act はGitHub Actionsの .github/workflows/*.yml をローカルで実行するCLIツール。Dockerを使ってGitHub Actionsのランナー環境を再現する。
# ワークフローを実行
act
# 特定のイベントをトリガー
act push
# 特定のジョブを実行
act -j build
# ドライラン(実行せず確認のみ)
act --dryrun
GitHub Actions本体との主な違いは:
- GitHub発行のトークン(
GITHUB_TOKEN)はダミー値になる - サービスコンテナ(MySQL/Redis等)は別途設定が必要
macos-latestランナーはDocker環境で再現できない(後述)
OrbStackをactのDockerバックエンドに設定する
デフォルトのact設定ではシステムのDocker socketを参照するが、OrbStackのsocketに明示的に向けることで安定性が上がる。
# OrbStackのDocker socket確認
ls -la ~/.orbstack/run/docker.sock
# actにsocketを指定して実行
act --container-daemon-socket /Users/$(whoami)/.orbstack/run/docker.sock
毎回指定するのが面倒なので、~/.config/act/actrc に設定する:
# ~/.config/act/actrc
--container-daemon-socket /Users/[yourusername]/.orbstack/run/docker.sock
または ~/.actrc に書いてもいい(actは両方を参照する):
# ~/.actrc
-P ubuntu-latest=catthehacker/ubuntu:act-latest
--container-daemon-socket /Users/[yourusername]/.orbstack/run/docker.sock
設定後は通常の act コマンドだけでOrbStackがDockerバックエンドとして使われる。
ランナーイメージの選択
ubuntu-latest ランナーに対して、actが使うDockerイメージを指定する。
公式推奨はGitHub Actionsの環境に近い catthehacker のイメージ :
# サイズ選択肢(小さい順)
# micro: 最小限(Node.js等なし)
act -P ubuntu-latest=catthehacker/ubuntu:act-22.04
# full: GitHub Actionsの ubuntu-latest に近い(10GB超え)
act -P ubuntu-latest=catthehacker/ubuntu:full-22.04
~/.actrc に書いておく:
-P ubuntu-latest=catthehacker/ubuntu:act-latest
-P ubuntu-22.04=catthehacker/ubuntu:act-22.04
-P ubuntu-20.04=catthehacker/ubuntu:act-20.04
macos-latest はDockerで再現できないため、macOS固有のステップを含むジョブはスキップされる。
# .github/workflows/ci.yml
jobs:
build:
runs-on: ubuntu-latest # ← actで動く
ios-build:
runs-on: macos-latest # ← actではスキップ
環境変数とシークレットの管理
CI環境では ${{ secrets.API_KEY }} のようなシークレットを参照するが、ローカルでは別途提供する必要がある。
.secrets ファイルに書く(.gitignore に追加必須):
# .secrets(プロジェクトルート)
DATABASE_URL=postgresql://postgres:password@localhost:5432/myapp_test
API_KEY=your-local-api-key-here
STRIPE_SECRET_KEY=sk_test_xxxxx
実行時に指定:
act --secret-file .secrets
# または個別に指定
act -s API_KEY=your-api-key
複数環境を使い分ける場合:
# ステージング用シークレット
act --secret-file .secrets.staging
# 本番と同じ設定でテスト
act --secret-file .secrets.production push
.secrets は絶対にgitにコミットしない。.gitignore に追加:
.secrets
.secrets.*
サービスコンテナ(DB・Redis)を扱う
ワークフローに services: ブロックがある場合、actが自動でコンテナを起動する。
# .github/workflows/ci.yml
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- run: npm test
actはこの services: ブロックを読んでPostgreSQLコンテナを起動してからジョブを実行する。OrbStackが裏で動いているので起動が速い。
サービスコンテナへの接続情報はランナー内の環境変数から取れる:
# ランナー内からはサービス名でアクセス可能
POSTGRES_HOST=postgres # サービス名がそのままホスト名
POSTGRES_PORT=5432
実際の使い方パターン
Node.js + PostgreSQL プロジェクト
# .github/workflows/test.yml
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
db:
image: postgres:16-alpine
env:
POSTGRES_DB: test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run migrate
env:
DATABASE_URL: postgresql://postgres:postgres@db:5432/test
- run: npm test
env:
DATABASE_URL: postgresql://postgres:postgres@db:5432/test
ローカルで実行:
act push --secret-file .secrets
Claude CodeのCLAUDE.mdにact環境を記述する
actをプロジェクトに導入したら、CLAUDE.mdに記述しておく。Claude CodeがCI確認を含む開発フローをこなせるようになる。
## CI/CD
ローカルCIは `act` で実行(actrcにOrbStack設定済み)。
Push前確認:
```bash
# 全ジョブ実行
act push --secret-file .secrets
# テストのみ
act -j test --secret-file .secrets
# ドライラン(ジョブ構造確認)
act --dryrun
CIが落ちたとき:
act push --secret-file .secrets -vで詳細ログ確認- 問題のあるステップを特定 → 修正 → 再実行
- ローカルで通ってからGitHubにPush
この記述があると、Claude Codeはコード変更後に「act でCI確認しますか?」と提案するか、自動でローカルCI確認を実行するようになる。
---
## よくある問題と解決策
### イメージのpullに時間がかかる
catthehackerのfullイメージは10GB以上ある。最初のpullは時間がかかる。
```bash
# 事前にpullしておく
docker pull catthehacker/ubuntu:act-latest
2回目以降はOrbStackがキャッシュするので速い。
GITHUB_TOKEN が原因でステップが落ちる
GitHub公式のActionの一部(gh CLIを使うステップ等)はGITHUB_TOKEN が必要。
# ダミートークンを設定(大半の場合これで通る)
act -s GITHUB_TOKEN=dummy_token
# 本物のトークンが必要な場合はPersonal Access Tokenを使う
act -s GITHUB_TOKEN=ghp_xxxxxxxxxxxx
docker network 関連のエラー
actがDockerネットワークを作成できない場合。
# act に --network オプションを渡す
act --network host
# または actrc に追加
echo "--network host" >> ~/.actrc
Apple Silicon でのイメージ互換性
一部のCIで使うイメージが linux/amd64 のみの場合。
# Rosettaが有効ならそのまま動く(設定12項目の3番参照)
# 動かない場合はイメージを arm64 版に変更するかQEMUを使う
docker run --platform linux/amd64 catthehacker/ubuntu:act-latest
まとめ
act + OrbStackの組み合わせで得られるもの:
- Push前にCIが通るか確認できる
- ローカルとCI環境の差異を最小化できる
- ネットワーク転送なしで高速にCIを回せる
- Claude CodeがCI確認を含む開発フローに参加できる
セットアップは30分もかからない。初回のイメージpullに時間がかかるが、2回目以降はOrbStackのキャッシュで速くなる。
「CIだけ落ちる」問題を減らすだけで、開発のフラストレーションがかなり下がる。


