devcontainer で Claude Code を安全に大暴れさせるためのレシピを考える
AIが自律的に働いているとき「破壊的な処理を実行してしまわないか」という心配事があります。その対策のひとつとして、プロジェクトをサンドボックスで隔離して、外界に影響を与えない環境で安全に開発をさせたい。それを可能にする技術のひとつが devcontainer であるわけで、今回は devcontainer + Claude Code の開発環境を試してみました。
devcontainer とは
devcontainer は devcontainer.json
という設定ファイルで開発環境のコンテナを定義・構築する仕組みです。もともとは VS Code の一機能だったのが、VS Code の外でも使えるように仕様が標準化されたものらしいです。
devcontainer は設定ファイルの記述に沿って Docker コンテナをビルドし、起動します。ローカルにあるプロジェクトのコードベースをコンテナにマウントし、コンテナの中にはいって開発をおこないます。コンテナの中からはホストOSのあれこれは触れないので、安全に開発がおこなえます。
Dev Container CLI
VS Code ではUIで簡単に利用できるので、はじめて試す場合はそちらがちょうど良いかもしれませんが、今回は Claude Code と一緒に使う前提です。せっかく CLI で完結しているところなので、 devcontainer もコマンドで起動させようと思います。
npm パッケージなので node が動く環境であれば使えます。導入もいつもの様に。
npm i -g @devcontainers/cli
基本的な使い方は、まず up
サブコマンドでコンテナをビルドして起動し、 exec
サブコマンドでコンテナの中に入ります。
devcontainer up --workspace-folder the/path/to/project
up
サブコマンドはデフォルトで workspace folder の中にある .devcontainer/devcontainer.json
を探して使いますが、別の場所にある devcontainer.json
を --config
オプションで指定して使わせることもできます。 --config
を使うことで、複数の workspace で共通の設定の devcontainer を立ち上げることができます。共通なのは設定だけであって、コンテナ自体は workspace ごとに作成されます。
devcontainer up --workspace-folder the/path/to/project \
--config ~/.config/devcontainer/devcontainer.json
コンテナを立ち上げたら exec
で中に入ります。 exec
は docker exec
と似た要領で、何のコマンドで起動するかを渡します。(下の例では /bin/bash
) exec
は --workspace-folder
と --config
を手がかりにしてコンテナを探すので、 up
した時と同じオプションを渡さなければいけません。
devcontainer exec --workspace-folder the/path/to/project \
--config ~/.config/devcontainer/devcontainer.json \
/bin/bash
devcontainer.json のレシピ
さて次は、Claude Code のコンテナを立ち上げるための devcontainer.json
のレシピです。色々試してみた結果、次のような形に辿り着きました。
{
"name": "Node.js & TypeScript",
"image": "mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm",
"remoteUser": "node",
"features": {
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}
},
"mounts": [
"type=bind,src=${localEnv:HOME}/.claude,dst=/home/node/.claude_host,readonly"
],
"postCreateCommand": "mkdir -p ~/.claude && cp -r ~/.claude_host/agents ~/.claude_host/commands ~/.claude_host/CLAUDE.md ~/.claude"
}
ghcr.io/anthropics/devcontainer-features/claude-code:1.0
というのが Anthropic 公式から提供されている devcontainer 用の feature です。
mounts
ではホストOSのホームディレクトリにある .claude
ディレクトリを別名 .claude_host
としてマウントし、 postCreateCommand
でその中の一部をコンテナの .claude
ディレクトリにコピーしています。こうすることで、いままで手塩にかけて育ててきたサブエージェントやカスタムスラッシュコマンドといった Claude Code の共有資産をコンテナの中でも活用することができます。
.claude
ディレクトリを同名でマウントしてそのまま使う方法もあるのですが、これは推奨できません。 Claude Code は .claude
に色々と書き込みをするものです。せっかくサンドボックスに隔離しているのに、ホストOSの環境を汚染することができる穴を残しておいては道理にあいません。
この devcontainer.json
を、自分は ~/.config/devcontainer/claude/devcontainer.json
に保存して共有で使うことにしました。
devclaude コマンド
毎度毎度長いオプションをつけて up
して exec
するのは面倒なので、シェルコマンドにまとめてしまうことにしました。 devclaude
という名前で作ります。
#!/bin/bash
# devclaude - DevContainer for Claude
# Usage: devclaude <workspace-folder-path>
WORKSPACE_FOLDER="$1"
CONFIG_FILE="$HOME/.config/devcontainer/claude/devcontainer.json"
# Start DevContainer
echo "Starting DevContainer..."
echo "Workspace: $WORKSPACE_FOLDER"
echo "Config: $CONFIG_FILE"
devcontainer up \
--workspace-folder "$WORKSPACE_FOLDER" \
--config "$CONFIG_FILE"
# Check result
if [ $? -eq 0 ]; then
echo "DevContainer started successfully!"
# Connect to container
echo "Connecting to container..."
devcontainer exec \
--workspace-folder "$WORKSPACE_FOLDER" \
--config "$CONFIG_FILE" \
/bin/bash
else
echo "Error: Failed to start DevContainer" >&2
exit 1
fi
この devclaude
コマンドは引数に workspace folder を受け取ります。つまりプロジェクトルートディレクトリを渡せば、そのプロジェクト専用の Claude Code コンテナが立ち上がります。
devclaude projects/my-project
node ➜ /workspaces/my-project $
コンテナの中はどうなっているか、中に入ってどうしたらいいか
コンテナの中身は Debian Linux のようです。開発者が関心を持つのは主にホームディレクトリと workspaces ディレクトリです。
/
├── home/
│ └── node/
│ └── .claude
└── workspaces/
└── myproject/
└── <Project Code Base>
コンテナに入った時は /workspaces/myproject
に居ます。そこでそのまま claude
を実行すれば開発が開始できます。あとは、いつも通りです。
devcontainer + Claude Code 環境の注意点
試してみていくつか気になった点があったので記録しておきます。問題の解消方法が見つかったら追記しておこうと思います。もし知ってるよ!という方いたら是非教えて下さい。
1. 入ってる Claude Code のバージョンがやや古く、オートアップデートが働かない
公式の devcontainer feature で入る Claude Code のバージョンは、執筆時点では 1.0.57
でした。この時の最新バージョンは 1.0.72
です。
node ➜ /workspaces/sandbox $ claude --version
1.0.57 (Claude Code)
バージョンアップをしようにも、 auto update はうまく動きません。 claude update
も試しましたが失敗しました。
node ➜ /workspaces/sandbox $ claude update
Current version: 1.0.57
Checking for updates...
New version available: 1.0.72 (current: 1.0.57)
Installing update...
Warning: Could not determine installation type
Attempting global update based on file detection...
Using global installation update method...
Error: Failed to install update
Or consider migrating to a local installation with:
claude migrate-installer
結局のところ npm
で入れ直すのが一番手っ取り早かったです。もう少しスマートにできるとうれしい。
sudo npm i -g @anthropics-ai/claude-code
2. MCPがうまく動かない
あまり多くのMCPは試していないのですが、少なくとも docker
ベースのものは動かせないのでは、と踏んでいます。(使えるようにするにはコンテナ内で docker を使えるようにしなければならなそう)
それから Atlassian MCP(公式)のようにリモートのSSEで動くタイプについては、それ自体は動きそうな気はしますが認証がパスできません。 Claude Code の認証のようにハッシュをコピー&ペーストするタイプならいけますが、Atlassian は loalhost にコールバックを飛ばす方式で、どうしてもホストの localhost に着地してしまい、コンテナ内まで到達しません。
色々試してみようとは思いますが、 devcontainer を使いたい理由に回帰してみると、MCPに依存せずに閉じた世界で Claude Code に大暴れしてもらう運用でも良いのかなと。
おわりに
まだちゃんと実運用はしてないのでなんとも言えないですが、取り敢えず起動して運用することが出来るレシピまで到達しました。また課題など見つけたら改善していきましょう。
Discussion