カテゴリー / インストール・ログイン・設定

Claude Code Dockerで隔離実行の手順とDev Container設定の要点

この記事の目次

Claude CodeをDockerで動かすなら、公式が用意している方法は「Dev Container」です(公式: Development containers)。.devcontainer/devcontainer.json の features に "ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {} を足してコンテナを再ビルドし、コンテナ内のターミナルで claude を実行して認証の案内に従います。サインインが終わると、ターミナルに Login successful と表示されます(公式: Authentication)。Claudeが実行するコマンドはホストではなくコンテナの中で動き、プロジェクトのファイル編集はローカルのリポジトリに反映されます。

ただし、コンテナに入れただけで安全になるわけではありません。再ビルドのたびにサインインが消える、rootのままだと確認省略フラグが使えない、rootで / からインストールするとハングすることがある、といったDocker特有の詰まりどころもあります。この記事では、公式ドキュメントの記述に沿って、設定から失敗時の切り分けまでを順に説明します。

Claude Code Dockerで隔離すると何が守られ、何が守られないのか

Dev Containerに入れると、Claude Codeが走らせるコマンド、言語サーバー、ビルドツールはすべてコンテナ内で動きます。VS Codeでは拡張機能のパネルも統合ターミナルの claude もコンテナ内で動きます。

一方で、公式(Development containers、Choose a sandbox environment)は守られない範囲もはっきり書いています。

  • プロジェクトのディレクトリは書き込み可能なマウント先として扱われるので、Claude Codeはそのコードを書き換えられます。変更はホストにそのまま現れます。
  • 外向きの通信を許している限り、Claudeが読めるデータは外へ送り出せます。
  • --dangerously-skip-permissions で動かした場合、悪意のあるプロジェクトがコンテナ内にあるもの、つまり ~/.claude に保存されたClaude Codeの認証情報まで持ち出すことは防げません。
  • 隔離してもモデルに送られる内容は変わりません。プロンプトやClaudeが読んだファイルは、隔離の有無に関係なくAPIへ送信されます。

このため公式は、Dev Containerは信頼できるリポジトリでだけ使い、~/.ssh やクラウドの認証ファイルをコンテナにマウントせず、リポジトリ単位や短命のトークンを使うよう勧めています。

権限モードは「そのツール呼び出しを実行するか、先に確認するか」を決め、隔離は「実行されたコマンドが何に触れるか」を制限します。権限モードそのものはClaude Codeの権限モードの解説で扱っています。

Dockerを使う方法と使わない方法はどう違うのか

公式の「Choose a sandbox environment」には、隔離方式の比較表があります。要点を日本語にすると次のとおりです。

方式 隔離される範囲 Docker 手間
組み込みのBashサンドボックス Bash・PowerShell・Monitorツールのコマンドと子プロセス 不要 macOSは最小、Linux・WSL2は低
sandbox runtime Claude Codeのプロセス全体(ファイルツール、MCPサーバー、hooksを含む) 不要 低
Dev Container 開発環境全体 必要 中
自前のコンテナ 開発環境全体 必要 中〜高
仮想マシン OS全体 不要 高

違いが大きいのは、組み込みのBashサンドボックスとそれ以外です。Bashサンドボックスはシェルコマンドだけを制限し、ReadやEditといったファイルツール、MCPサーバー、hooksはホスト上でそのまま動きます。Dev Containerを含む他の方式は、Claude Codeのプロセスごとコンテナ境界の中に入れます。

公式の推奨を目的別に整理すると、こうなります。

  • 自分のマシンで日常的に確認プロンプトを減らしたい: /sandbox で設定するBashサンドボックス(Claude Codeのサンドボックス設定で解説)
  • --dangerously-skip-permissions やauto modeで無人実行したい: Dev Container、任意のコンテナかVM、またはsandbox runtime
  • チームで同じ隔離環境をそろえたい: 公式の参照Dev Containerをリポジトリにコピー
  • 信頼できないリポジトリを扱う: 専用の仮想マシンか、Claudeのサブスクリプションがあればクラウドセッション
  • ネイティブWindowsで使う: コンテナかVM、またはWSL2内でBashサンドボックス

公式は、任意のDocker・OCIイメージでもClaude Codeを動かせるとしています(比較表の「自前のコンテナ」)。その場合は、書き込み可能なマウント、コンテナ内から届く認証情報とトークン、外向き通信の方針を自分で確認する必要があります。

Dev ContainerにClaude Codeを入れる手順は?

Claude Codeは、公式の「Claude Code Dev Container Feature」で任意のDev Containerに入ります(公式: Development containers)。VS Code、GitHub Codespaces、JetBrains IDE、CursorなどDev Containers仕様に対応したエディタで使えます。

1. devcontainer.jsonを作る

リポジトリに .devcontainer/devcontainer.json として保存します。既存のファイルがあれば features のブロックだけを足します。

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

image の行は自分のプロジェクトのベースイメージに置き換え、Dockerfileを使っている場合は削除します。末尾の :1.0 が固定するのはFeatureのインストールスクリプトの版で、Claude Code本体の版ではありません。Featureは最新のClaude Codeを入れ、コンテナ内でも既定で自動更新されます。VS CodeかCodespacesで開くと、Claude CodeのVS Code拡張も一緒に追加されます。

Node.jsはベースイメージに無ければFeatureが自分で入れます。

2. コンテナを再ビルドする

VS Codeのコマンドパレット(Macは Cmd+Shift+P、WindowsとLinuxは Ctrl+Shift+P)を開き、Dev Containers: Rebuild Container を実行します。

3. コンテナ内でサインインする

再ビルドしたコンテナでターミナルを開き、claude を実行して認証の案内に従います。AnthropicのアカウントならブラウザでClaudeかAnthropic Consoleのアカウントにサインインします。Amazon Bedrock、Google CloudのAgent Platform、Microsoft Foundryの場合はクラウドの認証情報を使い、ブラウザでの認証プロンプトは出ません。クラウドの認証情報はホストのファイルをマウントせず、containerEnv、Codespacesのシークレット、ワークロードIDで環境変数として渡します。

完成形を先に見たい場合は、anthropics/claude-code リポジトリの参照コンテナが使えます。CLI、外向き通信のファイアウォール、永続ボリューム、Zshを組み合わせた例で、devcontainer.json、Dockerfile、init-firewall.sh の3ファイルで構成されています。公式は「保守されたベースイメージではなく動作例」と位置づけているので、自分の構成に取り込む前の見本として使います。

再ビルドするたびにサインインが消えるのを防ぐには?

既定では、再ビルドでDockerコンテナのホームディレクトリに認証状態が残らないため、毎回サインインし直しになります。ここで間違えやすいのが、~/.claude だけをボリュームにしても解決しない点です。認証トークンやユーザー設定、セッション履歴は ~/.claude にありますが、OAuthアカウントや個人のMCPサーバー、プロジェクトごとの信頼情報はその外の ~/.claude.json に保存されます。

公式(Development containers)の対処は、名前付きボリュームを ~/.claude にマウントし、CLAUDE_CONFIG_DIR を同じパスに設定して .claude.json もボリュームの中に書かせる方法です。devcontainer.json では次の2か所を書きます。

  • mounts: source=claude-code-config,target=<ホーム>/.claude,type=volume の形で名前付きボリュームを指定する
  • containerEnv: CLAUDE_CONFIG_DIR に、上の target と同じパスを入れる

<ホーム> は自分のコンテナの remoteUser のホームディレクトリです。公式の例は remoteUser が node の構成で、そのユーザーのホーム配下の .claude を指定しています。すでに containerEnv がある場合は、2つ目を作らず既存のオブジェクトに追記します。リポジトリごとに状態を分けたいときは、ボリューム名に ${devcontainerId} を含めます。参照構成は source=claude-code-config-${devcontainerId} を使っています。

GitHub Codespacesでは、停止と起動では ~/.claude が残り、再ビルドで消えます。Codespaces間で認証を持ち回るなら、ANTHROPIC_API_KEY か、claude setup-token で発行した CLAUDE_CODE_OAUTH_TOKEN をCodespacesのシークレットに登録します。claude setup-token は1年有効のOAuthトークンを発行するコマンドで、トークンはブラウザで承認すると端末に表示され、どこにも保存されないので、コピーして使います。

–dangerously-skip-permissionsはどんな条件で使えるのか

公式(Development containers)は、コンテナが非rootユーザーでClaude Codeを動かし、コマンド実行をコンテナ内に閉じ込めることを前提に、無人実行のために --dangerously-skip-permissions を渡せるとしています。条件は次の2つです。

  • 非rootで起動する: CLIはrootで起動されるとこのフラグを拒否します。公式は、LinuxとmacOSではrootだと起動を拒否すると書いています。remoteUser が非rootのアカウントになっているか確認します。
  • 境界の中で動かす: 公式は、このフラグを使うセッションは常にコンテナ、VM、sandbox runtimeのいずれかの中で動かすよう求めています。

確認を省いても、バインドマウントしたワークスペースのファイルは書き換えられ、ホストにそのまま反映されます。Dockerコンテナのネットワーク方針が許す先にも到達できます。そのため、外向き通信の制限と組み合わせます。

通信制限について、参照コンテナには許可した宛先だけに外向き通信を絞る init-firewall.sh があります。コンテナ内でファイアウォールを動かすには追加の権限が要るため、参照構成は runArgs で NET_ADMIN と NET_RAW のケーパビリティを付けています。このスクリプトと権限はClaude Code自体には必須ではなく、自前のネットワーク制御で代替してもかまいません。許可リストに必要な宛先は、後述の切り分けの節にまとめています。

確認を減らしつつ安全チェックは残したいなら、実行前に分類器がアクションを審査するauto modeという選択肢もあります。逆に、組織としてこのフラグを使わせたくない場合は、managed settingsで permissions.disableBypassPermissionsMode を "disable" にします。

チームの設定や版をコンテナでそろえるには?

Claude CodeはLinuxで /etc/claude-code/managed-settings.json を最優先で読むため(公式: Development containers)、Dockerfileでコピーしておけば、各自の ~/.claude やプロジェクトの .claude/ の設定より優先されます。

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

ただし、Dockerfileはリポジトリにあるので、書き込み権限があれば誰でもこの手順を変更・削除できます。公式も、リポジトリにDev Containerを置くことは標準化の慣習であって強制の境界ではない、としています。回避されては困る方針は、サーバー管理の設定やMDMで配ります。

環境変数は containerEnv に書くと、コンテナ内のすべてのClaude Codeセッションに適用されます。テレメトリとエラー報告を止め、インストール後の自動更新を止める公式の例です。

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

CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC はフィーチャーフラグの取得も止めるため、Remote Controlなどそれに依存する機能はコンテナ内で使えなくなります。

Featureは常に最新版を入れるので、ビルドを再現可能にしたい場合はFeatureを使わず、Dockerfileで npm install -g @anthropic-ai/claude-code@X.Y.Z のように版を指定してインストールし(X.Y.Z は固定したい版番号)、DISABLE_AUTOUPDATER を 1 にします。

MCPサーバーをコンテナで使う場合は、リポジトリ直下の .mcp.json にプロジェクトスコープで定義し、stdioサーバーが必要とするバイナリはDockerfileで入れ、リモートサーバーのドメインは外部通信の許可リストに加えます。MCPそのものの設定はClaude Code MCPガイドを参照してください。

Dockerで動かないときはどこを確認すればよいか

公式ドキュメント(Troubleshoot installation and login、Configure the sandboxed Bash tool、Enterprise network configuration)に記載のある、Docker・コンテナ特有の失敗と対処をまとめます。

ビルドが Failed to install Node.js and npm で止まる FeatureによるNode.jsのインストールが失敗しています。features ブロックのClaude Code Featureより上に "ghcr.io/devcontainers/features/node:1": {} を追加し、再ビルドします。

Dockerfileでのインストールがハングする コンテナ内でrootとして / にインストールするとハングすることがあります。/ から実行するとインストーラーがファイルシステム全体を走査し、メモリを大量に使うためです。先に作業ディレクトリを設定します。

WORKDIR /tmp
RUN curl -fsSL https://claude.ai/install.sh | bash

Docker Desktopを使っている場合は、ビルド中のコンテナがDocker Desktopの仮想マシンに割り当てたメモリを共有します。Settings > Resources でメモリの上限を上げて、ビルドをやり直します。

ブラウザでサインインしたのに完了しない コンテナ内では、ブラウザが別のホストで開くため、リダイレクトがClaude Codeのローカルのコールバックサーバーに届かないことがあります。エディタのポート転送がlocalhostのコールバックを中継しない場合にも起こります。ブラウザに表示されたログインコードをコピーし、ターミナルの Paste code here if prompted に貼り付けます。完了すると Login successful と表示されます。それでも進まない場合はClaude Codeにログインできないときの対処で原因を切り分けてください。

コンテナの外向き通信を絞ったら接続できない 公式のネットワーク要件では、api.anthropic.com がAPIリクエストに、claude.ai がclaude.aiアカウントの認証に、platform.claude.com がConsoleアカウントの認証とclaude.aiアカウントのトークン交換・更新に使われます。この3つが許可リストに入っているか確認します。

コンテナ内でBashサンドボックスを重ねたら Operation not permitted になる 非特権コンテナでは、bubblewrapが新しい /proc をマウントできず、Can't mount proc on /newroot/proc: Operation not permitted のようなエラーになります。enableWeakerNestedSandbox を true にすると、コンテナ既存の /proc をバインドマウントして動きます。この設定はプロセス情報をサンドボックス内のコマンドに見せてしまうため、外側のコンテナが必要な隔離を担っている場合に限って使います。

ホストのBashサンドボックスから docker コマンドが失敗する コンテナの外、ホスト側でBashサンドボックスを有効にしている場合、docker はサンドボックスと互換性がありません。excludedCommands に docker compose * のようなパターンを入れて対象から外します。除外したコマンドはフル権限で動くので、docker * のような広いパターンは避け、必要な範囲に絞ります。

この記事が照合した公式ページ

この記事のコマンド名・設定キー・宛先は、2026年10月19日に次の公式ページと照合した内容です。設定をチーム環境に入れる前に、各ページの現行版と突き合わせてください。

組織としてのセキュリティ方針づくりはClaude Code法人導入のセキュリティガイドで扱っています。