Claude Code を Dev Container で動かす

Claude Code エンジニアリング 8分で読めます

Dev Container を使うと、チーム全員が同じ隔離された開発環境を再現できます。その中に Claude Code を入れると、Claude が実行するコマンドはホストではなくコンテナ内で走り、編集したファイルだけが手元のリポジトリに現れます。この記事では公式ドキュメントに基づき、導入手順と、認証の永続化・組織ポリシー・外向き通信の制限という3つの実運用の論点を整理します。

Dev Container を使う理由

Dev Container は Docker コンテナとして動きます。置き場所は自分のマシンでも、GitHub Codespaces のようなクラウドホストでも構いません。VS Code、GitHub Codespaces、JetBrains 系 IDE、Cursor のように Dev Containers 仕様に対応したエディタがそのコンテナへ接続し、ファイルの閲覧と編集はエディタでいつもどおり行いながら、統合ターミナル・言語サーバー・ビルドツールはすべてコンテナ内で動きます。Dev Container に対応していないエディタ(素の Vim など)は、このワークフローの対象外です。

Claude Code をコンテナ内で動かすと、プロジェクトのツールチェーンとまったく同じファイル・依存関係・ツールを見ることになります。VS Code では拡張機能のパネルからでも、統合ターミナルで claude を実行してでも構いません。どちらもコンテナ内で動き、同じ ~/.claude の設定を共有します。

ただし万能ではありません。公式は次のように警告しています。--dangerously-skip-permissions を付けて実行した場合、Dev Container は悪意あるプロジェクトがコンテナ内でアクセスできるもの(~/.claude に保存された Claude Code の資格情報を含む)を持ち出すことを防げません。信頼できるリポジトリでのみ使い、~/.ssh やクラウドの資格情報ファイルのようなホストの秘密情報をコンテナへマウントしないでください。リポジトリ単位、あるいは短命のトークンを使うほうが安全です。

Claude Code を Dev Container に入れる

Claude Code は Dev Container Feature としてどのコンテナにも入れられます。VS Code を例に、手順は3つです。

まず .devcontainer/devcontainer.json を作るか、既存のファイルに features ブロックを足します。

{
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
  "features": {
    "ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}
  }
}

末尾の :1.0 というバージョンタグが固定するのはFeature のインストールスクリプトであって、Claude Code のリリースではありません。Feature は最新の Claude Code を入れ、コンテナ内の Claude Code は既定で自動更新します。image の行は自分のプロジェクトのベースイメージに置き換えるか、Dockerfile を使っているなら削除します。

ベースイメージに Node.js が無い場合、Feature は自分で Node.js を入れます。それが失敗して Failed to install Node.js and npm でビルドが止まったときは、features ブロックの Claude Code より上に "ghcr.io/devcontainers/features/node:1": {} を足して再ビルドしてください。

次にコンテナを再ビルドします。VS Code ならコマンドパレット(Mac は Cmd+Shift+P、Windows と Linux は Ctrl+Shift+P)から Dev Containers: Rebuild Container を実行します。

最後に、再ビルドされたコンテナでターミナルを開いて claude を実行し、認証プロンプトに従います。Anthropic のアカウントならブラウザでサインインします。Amazon Bedrock、Google Cloud の Agent Platform、Microsoft Foundry を使う場合はクラウド側の資格情報が使われ、ブラウザは開きません。ブラウザでのサインインは完了したのにコールバックがコンテナへ届かないときは、ブラウザに表示されたコードをターミナルの Paste code here if prompted に貼り付けます。

再ビルドをまたいで認証を保持する

既定ではコンテナのホームディレクトリは再ビルドで捨てられるため、そのままだと毎回サインインし直すことになります。Claude Code は認証トークン・ユーザー設定・セッション履歴を ~/.claude に置きますが、OAuth アカウント・個人の MCP サーバー・プロジェクトごとの信頼設定は ~/.claude.json という別ファイルに置きます。つまり ~/.claude にボリュームをマウントしただけではサインインは維持されません。

名前付きボリュームを ~/.claude にマウントし、CLAUDE_CONFIG_DIR を同じパスに設定して .claude.json もボリューム内に書かせます。次は remoteUsernode のコンテナの例です。

"mounts": [
  "source=claude-code-config,target=/home/node/.claude,type=volume"
],
"containerEnv": {
  "CLAUDE_CONFIG_DIR": "/home/node/.claude"
}

/home/node は自分のコンテナの remoteUser のホームディレクトリに置き換えます。すでに containerEnv がある場合は、2つ目を足すのではなくそのオブジェクトに CLAUDE_CONFIG_DIR を加えてください。リポジトリごとに状態を分けたい場合は、ボリューム名に ${devcontainerId} 変数を含めます。

GitHub Codespaces では、~/.claude は停止・再開では残りますが、コンテナを再ビルドすると消えます。上の設定はそこでも同じように効きます。Codespace をまたいで認証を持ち回りたい場合は、ANTHROPIC_API_KEYclaude setup-token で作った CLAUDE_CODE_OAUTH_TOKEN を Codespaces のシークレットとして登録します。

組織ポリシーを適用する

同じイメージと設定が全員のマシンで動くので、Dev Container は組織のポリシーを効かせる場所として都合が良い場所です。

Claude Code は Linux では /etc/claude-code/managed-settings.json を読み、設定の階層のうち最も高い優先度で適用します。つまりそこに書いた値は、開発者が ~/.claude やプロジェクトの .claude/ に書いた設定を上書きします。Dockerfile から配置できます。

RUN mkdir -p /etc/claude-code
COPY managed-settings.json /etc/claude-code/managed-settings.json

ただし Dockerfile はリポジトリの中にあるので、書き込み権限のある人はこの手順を変更・削除できます。開発者が編集して回避できないポリシーが必要なら、サーバー管理設定か MDM 経由で配ってください。

コンテナ内の全セッションに効かせたい環境変数は devcontainer.jsoncontainerEnv に書きます。次はテレメトリとエラー報告を止め、インストール後の自動更新を無効にする例です。

"containerEnv": {
  "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
  "DISABLE_AUTOUPDATER": "1"
}

ひとつ副作用があります。CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC はフィーチャーフラグの評価も止めるため、そのコンテナのセッションでは Remote Control が使えなくなります。

また Dev Container Feature は常に最新の Claude Code を入れます。再現性のためにバージョンを固定したいなら、Feature ではなく Dockerfile から npm install -g @anthropic-ai/claude-code@X.Y.Z で入れ、あわせて DISABLE_AUTOUPDATER を設定します。

外向き通信を制限する

コンテナの外向き通信を、Claude Code が必要とするドメインだけに絞ることができます。必要なドメインの一覧は公式のネットワーク要件のページにあります。

参照実装のコンテナには init-firewall.sh というスクリプトが含まれており、Claude Code と開発ツールが必要とするドメイン以外の外向き通信をすべて遮断します。コンテナ内でファイアウォールを動かすには追加の権限が要るため、参照実装は runArgsNET_ADMINNET_RAW のケーパビリティを付けています。

このファイアウォールとケーパビリティは Claude Code 自体に必須ではありません。自分の組織のネットワーク制御に任せるなら、外して構いません。

MCP サーバーをコンテナ内で使えるようにするには、リポジトリのルートに .mcp.json を置いてプロジェクトスコープで定義し、Dev Container の設定と一緒にコミットします。ローカルの stdio サーバーが依存するバイナリは Dockerfile で入れ、リモートサーバーのドメインはネットワークの許可リストに足してください。

権限プロンプト無しで動かすときの前提

コンテナは Claude Code を非 root ユーザーで動かし、コマンドの実行範囲をコンテナ内に閉じます。そのため --dangerously-skip-permissions を付けた無人実行の置き場所として使えます。ただし CLI は root で起動されたときこのフラグを拒否するので、remoteUser が非 root アカウントになっていることを確認してください。

権限プロンプトを飛ばすということは、ツール呼び出しを実行前に見直す機会を手放すということです。Claude はバインドマウントされたワークスペース内のどのファイルも変更でき(それはホスト上にそのまま現れます)、コンテナのネットワークポリシーが許すものにはどこへでも到達できます。前節の外向き通信の制限と組み合わせて、届く範囲を狭めておくのが前提になります。

安全性の検査を切らずにプロンプトだけ減らしたいなら、実行前に分類器が動作を確認する auto モードを検討してください。開発者に --dangerously-skip-permissions を一切使わせたくない場合は、管理設定で permissions.disableBypassPermissionsMode"disable" にします。

公式リポジトリ anthropics/claude-code には、CLI・外向きファイアウォール・永続ボリューム・Zsh ベースのシェルを組み合わせた参照用の Dev Container があります。維持されるベースイメージではなく動く例という位置づけなので、自分の構成に取り込む前に、各部品がどう噛み合っているかを見るために使うのが良い読み方です。

本記事は Claude Code 公式ドキュメント「Development containers」を元にした非公式の日本語解説です。最新の仕様は公式ドキュメントを確認してください。