こんにちは、橋本です。
この記事では、AIエージェント時代の開発において、Gitワークツリーを最大限活かすための開発環境構成を紹介します。
いきなりですが、みなさんはコーディングにおいて、どのAIツールを使っていますか? 私はClaude Code を使っています。もはやAIエージェントなしでは開発できないくらい、ほとんどのタスクで使用しています。
そしてClaude Codeやその他のAIエージェントを用いて開発していると、次のような欲が出てきます。
- 同時に機能開発やバグ修正をしたい
- AIが生成したコードを複数パターンで検証したい
- メインタスクのブランチを汚さずに別PRのレビューや動作確認をしたい
いちいちgit stashや無理にgit commitしたくないですよね...
AI x Gitワークツリーは便利
このような開発環境において、Gitワークツリー が強力な武器になります。
これはClaude Codeの公式ドキュメントでも推奨されている手法です。
# Gitワークツリー で複数ブランチを物理的に同時展開 git worktree add ../feature-auth -b feature/auth git worktree add ../feature-payment -b feature/payment git worktree add ../fix-bug123 -b fix/bug-123
~/projects/ ├── myapp/ # main ブランチ ├── feature-auth/ # feature/auth ブランチ ├── feature-payment/ # feature/payment ブランチ └── fix-bug123/ # fix/bug-123 ブランチ
このようにすれば、各ディレクトリで独立した開発サーバーを起動できるため、ブランチ切り替えなしで複数の機能を同時に開発・動作確認できます。
課題
しかし、複数環境を立ち上げると面倒なことがあります。
それは、ブランチごとにポートを変更して覚えておくのが大変ということです。
例えばDocker Composeでポートマッピングしている場合、ホスト側で同じポートを使おうとして衝突してしまいます。それを避けるために環境変数などでポートを変えても、結局どのポートがどのブランチ用か分からなくなってしまいます。
# 各ディレクトリでサーバーを起動すると... ~/myapp/ → localhost:3000 ~/feature-auth/ → localhost:3001 # ポートの衝突を避けるため変更 ~/feature-payment/ → localhost:3002 ~/fix-bug123/ → localhost:3003 # => どのポートがどのブランチ用か分からなくなる
OrbStack の Container domain names 機能
ここではまず、macOS ではここまで快適にできるという理想形として OrbStack を紹介します。 (Windows も含めた解決方法は後述します)
OrbStack とは
OrbStack is a fast, light, and simple way to run containers and Linux machines. It's a supercharged alternative to Docker Desktop and WSL, all in one easy-to-use app.
Google翻訳すると
OrbStackは、コンテナとLinuxマシンを高速、軽量、そしてシンプルに実行できるツールです。Docker DesktopやWSLに代わる強力な代替手段であり、オールインワンの使いやすいアプリです。
今回ご紹介するContainer domain names 機能を使わずとも、非常に魅力的なツールです。
Container domain names 機能
OrbStack にはContainer domain names 機能というものがあり、コンテナごとにドメインを自動で割り当ててくれます。 設定ゼロで利用可能で、以下のような特徴があります。
- docker-compose.yamlでポートマッピングしなくても、自動的に
<container-name>.orb.localや<service>.<project>.orb.localでアクセス可能 - hosts ファイルの編集不要
- HTTPS対応も自動
設定例
docker-compose.yaml
services: backend: build: ./backend volumes: - ./backend:/app - /app/node_modules frontend: build: ./frontend volumes: - ./frontend:/app - /app/node_modules depends_on: - backend
通常の Docker Compose では ports: - "3000:3000" のようにポートマッピングが必要ですが、OrbStack では不要です。
frontend/.env.example
API_BASE_URL=https://backend.orbstack-sample.orb.local
動作確認
# コンテナ起動
% cd ~/project-name
% docker compose up -d
# APIの確認
% curl https://backend.orbstack-sample.orb.local/api/hello
{"message":"Hello from API 1"}
# ブラウザでも確認
% open https://frontend.orbstack-sample.orb.local/

とても良いですね。Gitワークツリーを用いて複数ブランチでサーバーを起動しても、同じようにアクセスできます。
ちなみに、ドメインはOrbStackのコンテナのInfoから確認できます。

macOS 以外の環境でも同じ体験を再現したい
OrbStack の Container domain names 機能は非常に快適ですが、macOS 以外の環境では利用できません。チーム開発においても困ります。
そこでOrbStackを使わずに同じ体験を再現できないか?と考え、たどり着いたのが *.localhost サブドメイン + リバースプロキシ でした。
*.localhostの補足
The domain "localhost." and any names falling within ".localhost." are special in the following ways:
localhost は RFC 6761 で特別なドメインとして予約されているため、*.localhost はhosts ファイルの編集なしで 127.0.0.1 に解決されます。
DNS 解決とポート解決は別問題
しかし、DNS 解決だけでは解決になりません。「サブドメインでアクセスできる」だけでは不十分で、「どのコンテナのどのポートに流すか」を解決する必要があります。
そこで Caddy の出番です。
(もちろん Nginx でも可能ですが、Caddy は開発用証明書の自動生成も担ってくれるため、HTTPSにも対応しやすくて便利です)
Caddy x Docker Compose
caddy-docker-proxy を使い、OrbStackのContainer domain names 機能を模倣します。
ファイル構成
docker-sample/
├── docker-compose.yaml # アプリケーションサービス
├── docker-compose.network.yaml # Caddy
├── setup-worktree.sh # Gitワークツリーのセットアップスクリプト
├── .env # サブドメイン設定
├── .env.example # サブドメイン設定テンプレート
│
├── backend/
│ ├── Dockerfile
│ └── src/index.ts
│
└── frontend/
├── Dockerfile
├── .env
├── .env.example
└── src/App.tsx
docker-compose.network.yaml(インフラ用)
caddy-docker-proxyのREADME.md を参考に設定します。
services: caddy: image: lucaslorentz/caddy-docker-proxy:ci-alpine ports: - 80:80 - 443:443/tcp - 443:443/udp environment: - CADDY_INGRESS_NETWORKS=docker-sample-shared-net volumes: - /var/run/docker.sock:/var/run/docker.sock - caddy_data:/data networks: - shared_net restart: unless-stopped networks: shared_net: name: docker-sample-shared-net external: true volumes: caddy_data: {}
docker-compose.yaml(アプリケーション用)
labelsで Caddy のルーティングを宣言的に設定${SUBDOMAIN:-develop}により、環境変数でサブドメインを動的に変更可能external: trueで既存のネットワークに参加
services: backend: build: ./backend volumes: - ./backend:/app - /app/node_modules networks: - shared_net labels: caddy: "${SUBDOMAIN:-develop}.api.localhost" caddy.reverse_proxy: "{{upstreams 3000}}" frontend: build: ./frontend volumes: - ./frontend:/app - /app/node_modules networks: - shared_net labels: caddy: "${SUBDOMAIN:-develop}.localhost" caddy.reverse_proxy: "{{upstreams 3333}}" depends_on: - backend networks: shared_net: name: docker-sample-shared-net external: true
setup-worktree.sh
Gitワークツリーを本格的に使い始めると、 ブランチごとに .env を書き換える作業自体が新たなストレスになります。
そこで、Gitワークツリーの作成から環境構築までを一気に行うスクリプトを用意しました。
利用イメージ
% ./setup-worktree.sh feature/auth
処理の流れ
- 指定したブランチ名からディレクトリ名を生成(
/を-に変換) - 指定したブランチが存在しない場合は新規作成
- Gitワークツリーでディレクトリを作成
.envとfrontend/.envを設定- コンテナを起動
#!/bin/bash
# Cross-platform sed -i
sed_i() {
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' "$@"
else
sed -i "$@"
fi
}
BRANCH_NAME=$1
DIR_NAME=${BRANCH_NAME//\//-}
# Create worktree (create branch if it doesn't exist)
if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME"; then
git worktree add "../$DIR_NAME" "$BRANCH_NAME" || { return 1 2>/dev/null || exit 1; }
else
git worktree add -b "$BRANCH_NAME" "../$DIR_NAME" || { return 1 2>/dev/null || exit 1; }
fi
cd "../$DIR_NAME" || { echo "❌ Failed to cd into $DIR_NAME"; return 1 2>/dev/null || exit 1; }
# Set up environment files
cp .env.example .env
sed_i "s|SUBDOMAIN=.*|SUBDOMAIN=$DIR_NAME|" .env
cp frontend/.env.example frontend/.env
sed_i "s|API_BASE_URL=.*|API_BASE_URL=https://$DIR_NAME.api.localhost|" frontend/.env
# Start Docker containers
docker compose up -d
echo "✅ Ready at https://$DIR_NAME.localhost"
起動手順
初回セットアップ
# 共有ネットワークを作成
% docker network create docker-sample-shared-net
fcfaaca6b972cbf477603a0acc77d855f6b295e55f0379467842a7f6d9a2ca18
# Caddy コンテナを起動
% docker compose -f docker-compose.network.yml up -d
[+] Running 1/1
✔ Container docker-sample-caddy-1 Started
# Caddy のルート証明書をインストール(HTTPS 用)
# ブラウザで警告なしにアクセスするため、ローカルCAの証明書を信頼させます。
# 証明書をコンテナからコピー
% docker cp docker-sample-caddy-1:/data/caddy/pki/authorities/local/root.crt ./root.crt
Successfully copied 2.56kB to /Users/{username}/Documents/personal/docker-sample/root.crt
macOS の場合、ダウンロードしたroot.crtをFinderなどからダブルクリックすると、キーチェーンアクセスが開くので、証明書を「常に信頼 (Always Trust)」に設定します。

設定が成功すると、以下のように表示されます。

開発環境を立ち上げる
% docker compose up -d [+] Running 2/2 ✔ Container docker-sample-backend-1 Started ✔ Container docker-sample-frontend-1 Started
新しいブランチで開発環境を立ち上げる
% . ./setup-worktree.sh feature/sample2 Preparing worktree (checking out 'feature/sample2') HEAD is now at bd32d1e feat: Add cross-platform worktree setup script [+] Running 2/2 ✔ Container feature-sample2-backend-1 Started ✔ Container feature-sample2-frontend-1 Started ✅ Ready at https://feature-sample2.localhost
動作確認
どちらもきちんと動作しました。
(差分をわかりやすくするため、ソースコードを少し変更しています)
https://develop.localhostにアクセス
https://feature-sample2.localhostにアクセス
最後に
OrbStackもCaddyも素晴らしいですね。実際に試してみてとても良い体験だったので、弊社の開発環境にも導入できないか、試してみようと思います。
Legalscapeでは開発環境やCI/CDの改善にも継続的に取り組んでいますので、ご興味ある方はまずはぜひカジュアル面談をさせていただけると嬉しいです。お待ちしております!