Skip to content

chore(devcontainer): add Dev Container config for Claude Code isolated execution#686

Merged
takaokouji merged 5 commits into
developfrom
feature/devcontainer-claude-code
May 11, 2026
Merged

chore(devcontainer): add Dev Container config for Claude Code isolated execution#686
takaokouji merged 5 commits into
developfrom
feature/devcontainer-claude-code

Conversation

@takaokouji
Copy link
Copy Markdown

Summary

Claude Code をホスト直接実行するのではなく、devcontainer 内で動かすための設定を追加します。社内ガイドライン (NaCl Claude Code 利用ガイドライン v0.2) の 階層 B (OSS / 自社開発) の隔離環境推奨 に準拠することが目的です。

Why

ホスト直接実行では Claude Code が ~/.ssh, ~/.aws, 他案件ディレクトリなどに物理アクセスできてしまう。本プロジェクトの作業範囲は明確 (<repo> + 関連 OSS = ~/ghq 配下) なので、コンテナ内に限定することで「物理的にアクセスできる範囲」をホワイトリスト化する。

Changes Made

.devcontainer/devcontainer.json

  • 既存の docker-compose.ymlapp サービスを再利用する構成
  • ghcr.io/anthropics/devcontainer-features/claude-code:1.0 で Claude Code をインストール
  • ghcr.io/devcontainers/features/github-cli:1 で gh CLI を導入
  • forwardPorts: [8601] で dev server をホストに公開
  • postCreateCommandbin/setup-worktree を自動実行

.devcontainer/docker-compose.devcontainer.yml

既存 compose への override:

  • command: sleep infinity で devcontainer を長寿命化
  • 以下のマウントを追加 (ホワイトリスト):
ホスト側 コンテナ内 用途
~/ghq /ghq submodule の origin/upstream、関連 OSS 参照
~/.gitconfig /root/.gitconfig (ro) git ユーザー情報
~/.config/gh /root/.config/gh fine-grained PAT を含む gh CLI 認証

マウントしない: ~/.ssh, ~/.aws, ~/Documents, ~/Downloads, ~/Desktop, ~/Library

.devcontainer/README.md

起動方法 (VS Code Dev Containers / devpod / docker compose 直接実行)、設計方針、AWS CDK deploy の運用方針 (ホスト側で実行)、トラブルシューティングを記載。

Compatibility

既存の docker compose run --rm app ... / bin/dx / git worktree ワークフローには影響しません。devcontainer は 追加 であり、既存ユーザーは従来通り作業可能です。

Test Coverage

  • docker compose -f docker-compose.yml -f .devcontainer/docker-compose.devcontainer.yml config --quiet でマージ後の compose 設定が有効であることを確認済み
  • マージ後の app サービスに既存 4 volume + 追加 3 mount が正しく合成されることを確認済み

Manual Verification (これから)

実機での Reopen in Container 動作確認は別途実施します:

  • VS Code Dev Containers での起動
  • コンテナ内から gh auth status が成功すること
  • コンテナ内から /ghq 配下が見えること
  • コンテナ内から npm run lint が動くこと
  • devpod での起動確認 (brew install devpoddevpod up .)

Follow-up

  • Phase 2: bin/dx の devcontainer 内分岐
  • Phase 3: CLAUDE.md / .claude/rules/git-workflow.md にホスト直接 Claude Code 禁止を明記
  • Phase 4: devpod 動作確認の追記

Test plan

  • CI lint / build / unit / integration pass
  • VS Code Reopen in Container 成功
  • devcontainer 内で gh auth status 成功
  • devcontainer 内で ls /ghq で OSS リポジトリ群が見える
  • devcontainer 内で npm run lint が動く
  • devpod での起動確認

…d execution

Claude Code をホスト直接実行するのではなく、devcontainer 内で動かすための設定を
追加する。社内ガイドライン (NaCl Claude Code 利用ガイドライン v0.2) の階層 B
(OSS / 自社開発) の隔離環境推奨に準拠する。

## 設計方針

- 既存の `docker-compose.yml` の `app` サービスを再利用する override 構成
- 物理的にアクセスできる範囲をホワイトリスト方式で制限:
  - `<repo>` → `/app` (既存通り)
  - `~/ghq` → `/ghq` (submodule の origin/upstream、関連 OSS 参照)
  - `~/.gitconfig` → `/root/.gitconfig` (ro)
  - `~/.config/gh` → `/root/.config/gh` (fine-grained PAT)
- 以下は意図的にマウントしない:
  `~/.ssh`, `~/.aws`, `~/Documents`, `~/Downloads`, `~/Desktop`, `~/Library`
- VS Code Dev Containers / devpod / docker compose のいずれからでも起動可能

## ファイル

- `.devcontainer/devcontainer.json` — devcontainer 設定本体。claude-code feature
  と github-cli feature を追加
- `.devcontainer/docker-compose.devcontainer.yml` — 既存 compose への override
  (sleep infinity で長寿命化 + 追加マウント)
- `.devcontainer/README.md` — 起動方法、設計方針、トラブルシューティング

既存の `docker compose run --rm app ...` ワークフローには影響しない。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

macOS の `gh` は PAT を Keychain に保存するため、~/.config/gh を
bind mount しても oauth_token がコンテナに渡らない。実機検証で発覚した
問題への対処。

- devcontainer.json の remoteEnv に GH_TOKEN: ${localEnv:GH_TOKEN} を追加
- initialize.sh を新設し、GH_TOKEN 未設定時に警告を出す
- README に「ホスト側で `export GH_TOKEN=$(gh auth token)` してから起動」
  の手順を明記

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@takaokouji
Copy link
Copy Markdown
Author

実機検証結果と追加修正

main checkout で feature/devcontainer-claude-code を取り出し、docker compose -f docker-compose.yml -f .devcontainer/docker-compose.devcontainer.yml up -d app で実機検証しました。

✅ OK だった項目

  • compose merge: config --quiet で valid、app サービスに既存 4 volume + 追加 3 mount が正しく合成
  • コンテナ内マウント: /app, /ghq, /root/.config/gh, /root/.gitconfig がすべて存在
  • /ghq 配下: github.com/ 配下のリポジトリが見える
  • workspace 内 git: feature ブランチが正しく見える
  • npm run lint がコンテナ内で完走(既存の scratch-vm/test/fixtures/patch-timers.js 等の JSDoc warning 3 件は本 PR と無関係)

❌ 発見した問題と修正

macOS の gh は PAT を Keychain に保存するため、~/.config/gh を bind mount しても oauth_token がコンテナに渡らない。確認すると hosts.yml には user: takaokouji しかなく token は keychain 側にあった。

修正内容 (963896a)

  • devcontainer.jsonremoteEnv"GH_TOKEN": "${localEnv:GH_TOKEN}" を追加
  • .devcontainer/initialize.sh 新設(GH_TOKEN 未設定時に手順を案内)
  • README にホスト側手順を明記:
    export GH_TOKEN=$(gh auth token)

実機で GH_TOKEN をコンテナに env で渡したところ、コンテナ内で ${GH_TOKEN} の長さが正しく取得できることを確認しました(PAT が container にきちんと届く)。

⏳ 残りの実機検証

  • VS Code Dev Containers の Reopen in Container での起動(devcontainer features が apply される経路)
  • features 適用後の gh auth status 動作(GH_TOKEN 経由で smalruby/* に通り、takaokouji/* には 403 になること)
  • devpod での起動確認

takaokouji and others added 3 commits May 11, 2026 23:01
…Command

VS Code Reopen in Container を main checkout で実行したとき、
postCreateCommand の `bin/setup-worktree || true` が
"this script is for worktrees, not the main checkout" を stderr に出力し、
VS Code のターミナルに "error" として表示されていた (exit code 0 だが UX 上は失敗に見える)。

post-create.sh を新設し、git-common-dir と git-dir を比較して
worktree のときだけ bin/setup-worktree を実行するように修正。
main checkout では何もしない (env / node_modules / dist は既に揃っているため)。

加えて、Dev Containers CLI が `--experimental-lockfile` で生成した
devcontainer-lock.json をコミット (features の digest を固定してサプライチェーンを保護)。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
devcontainer 内で claude を起動するとログイン状態・設定・skills・memory が
リセットされてしまう問題への対応。素朴に ~/.claude 全体をマウントすると
他プロジェクトの transcripts/sessions/history が container から見えてしまうため、
選択的マウントを採用。

## マウントするもの (グローバルかつ共有して安全なもの)
- ~/.claude.json — 認証
- ~/.claude/settings.json (ro) — グローバル設定
- ~/.claude/skills/ (ro) — 自作スキル
- ~/.claude/plugins/ (ro) — プラグイン
- ~/.claude/statusline-command.sh (ro) — カスタム statusline

## マウントしないもの (他プロジェクト漏れ防止)
- ~/.claude/projects/ 全体, ~/.claude/sessions/, ~/.claude/history.jsonl
- ~/.claude/file-history/, ~/.claude/shell-snapshots/, ~/.claude/session-env/

## このプロジェクトの memory だけ共有する仕組み

ホスト側の per-project ディレクトリ名はユーザーのパスに依存。
コンテナ内では workspaceFolder=/app 固定なので slug は常に `-app`。
initialize.sh がホスト側に `-app` シンボリックリンクを作成し、
ホスト本来の slug を指すようにする。compose は `~/.claude/projects/-app` を
マウントし、コンテナの claude は透過的に同じ memory を読み書きできる。

他のユーザー / worktree / マシンに切り替えても、initialize.sh がそのときの
host slug を計算してリンクを張り直す。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
これまで docker-compose.devcontainer.yml に詰め込んでいた個人依存のマウント
(ghq, ~/.claude*) を docker-compose.local.yml に分離。本ファイルは gitignore
対象で、各自が .example からコピーして自分の環境に合わせる。

## ファイル構成

- docker-compose.devcontainer.yml (commit): 全員共通 (gitconfig, gh config)
- docker-compose.local.yml.example (commit): テンプレート (ghq, ~/.claude*)
- docker-compose.local.yml (gitignore): 各自カスタマイズ
- initialize.sh: ファイル無ければ空の services スタブを自動生成

## 理由

ghq の有無、Claude Code 利用の有無、~/ がどう構成されているかは開発者ごとに
異なる。共有 compose ファイルに個人依存のパスが残ると、他開発者の Reopen in
Container が起動失敗する (bind mount のソース不在で fail)。

## 動作

- Claude Code を使わない人: 何もしなくても起動する (空 stub だけが生成される)
- 個人 mount を有効化したい人: cp .example → .local.yml で開始

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@takaokouji takaokouji merged commit 7106710 into develop May 11, 2026
9 checks passed
@takaokouji takaokouji deleted the feature/devcontainer-claude-code branch May 11, 2026 14:30
github-actions Bot pushed a commit that referenced this pull request May 11, 2026
…ntainer-claude-code

chore(devcontainer): add Dev Container config for Claude Code isolated execution
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant