2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code + MCPサーバーをDevcontainerで使う個人的ベストプラクティス(GitHub MCP例)

2
Last updated at Posted at 2026-03-07

はじめに

私は普段、Devcontainer環境で開発環境を構築し、VSCodeの拡張機能(anthropic.claude-code)経由でClaude Codeを使っていました。

やはり話題になっているだけあって、Claude Codeのすごさは日々実感しています。コードの生成・修正はもちろん、プロジェクト全体を理解した上での提案や、ファイル横断でのリファクタリングなど、開発体験が大きく変わりました。

そうなると欲が出てくるもので、次はMCPサーバーの導入をしたいと思うようになりました。MCPサーバーを使えば、外部サービスと連携したりと、できることの幅がさらに広がります。

しかし、今まで「VSCode拡張機能を入れるだけ」で済んでいた自分にとって、MCPサーバーの導入は意外とハードルが高いものでした。

  • MCPサーバーによってはNode.jsが必要だと知らなかった
  • DevcontainerをRebuildするたびにClaude Codeの認証が消えてしまう
  • ClaudeCodeの導入方法が複数あってどれを選択したらいいか迷う

...といった具合に、細かいところでつまずきました。

いろいろ調べて試行錯誤した結果、現時点での個人的ベストプラクティスがまとまったので、GitHub MCPサーバーの導入を具体例として、環境構築手順を共有します。


始める前に知っておきたいこと

MCPサーバーをDevcontainer上で動かすには、いくつか事前に理解しておくべきポイントがあります。自分がつまずいた点を先に整理しておきます。

MCPサーバーの通信方式とランタイム

MCPサーバーには主に2つの通信方式があり、方式によって必要な準備が異なります。

方式 概要 ランタイム
stdio npxuvxでプロセスを起動し、標準入出力で通信する。 必要(Node.js, Python等)
HTTP (SSE) URLを指定してHTTPサーバーと通信する 不要

stdio方式の場合、起動コマンドに応じたランタイムが必要です。

ランタイム 起動コマンド 代表的なMCPサーバー
Node.js npx GitHub, Slack, Filesystem など多数
Python uvx 一部のPython製サーバー

この記事で扱うGitHub MCPサーバーはstdio方式でnpxで起動するため、Node.jsが必要です。(MCPサーバー自体がNode.jsで実装されているため)

Claude Codeの導入方法と設計判断

Devcontainer上でClaude Codeを使う方法は複数あります。

方法 概要
Dockerfileでインストール curl -fsSL https://claude.ai/install.sh | bash をDockerfileに記述
Devcontainer Featureで導入 公式のClaude Code Featureを宣言的に追加
コンテナ起動後に手動インストール 毎回手動で実行

など

本記事ではDockerfileに書く方式を採用しています。理由は、Claude Codeはプロジェクトの開発ツールとして中心的な存在であり、「コンテナのベース環境の一部」として扱うのが自然だと考えたためです。

ぶっちゃけDevcontainer Featureを活用しても全く問題ないと思います

(優先順位が低いのか、更新がかなり前だったので、なんとなく敬遠してしまったというのが本音)

一方、Node.jsのような汎用ツールはDevcontainer Featuresで導入しています。

Claude Codeはこの開発環境の中心的なツールであるためDockerfileに含め、Node.jsは汎用ランタイムとしてDevcontainer Featureに追加する形にしました。

Devcontainerを Rebuildすると認証が消える

Claude Codeの設定や認証情報は~/.claudeディレクトリに保存されます。DevcontainerはRebuildするとコンテナが作り直されるため、何もしないと毎回認証からやり直しです。これをDocker Named Volumeで解決します。


最終的なファイル構成

your-project/
├── .devcontainer/
│   ├── Dockerfile
│   └── devcontainer.json
├── .mcp.json          # MCPサーバー設定
├── .env               # APIトークン(Git管理外)
├── .gitignore
└── (ソースコード)

Dockerfile

FROM nvidia/cuda:12.8.1-cudnn-devel-ubuntu24.04

ENV DEBIAN_FRONTEND=noninteractive \
    PIP_ROOT_USER_ACTION=ignore \
    PYTHONPATH=/workspace \
    PATH=/opt/venv/bin:/root/.local/bin:${PATH} \
    LANG=en_US.UTF-8 \
    LANGUAGE=en_US:en \
    LC_ALL=en_US.UTF-8

RUN apt-get update && apt-get install -y --no-install-recommends \
    python3 \
    python3-pip \
    python3-dev \
    python3-venv \
    curl \
 && rm -rf /var/lib/apt/lists/*

WORKDIR /workspace

RUN python3 -m venv /opt/venv

# Python パッケージ(プロジェクトに応じて変更)
RUN /opt/venv/bin/python -m pip install --upgrade pip && \
    /opt/venv/bin/python -m pip install \
      numpy pandas scikit-learn ...

# Claude Code
RUN curl -fsSL https://claude.ai/install.sh | bash

CMD ["bash"]

ベースイメージはプロジェクトに応じて自由に変更してください。ここではGPU利用の機械学習プロジェクトを例にnvidia/cudaを使っています。

今回はCUDAベースイメージを使用しているため rootユーザーのまま運用しています。

ポイントは最後の部分です。

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

Claude Codeの公式インストールスクリプトを実行しています。これにより、コンテナ起動後すぐにターミナルでclaudeコマンドが使えるようになります。


devcontainer.json

{
  "name": "your-project-devcontainer",
  "build": {
    "dockerfile": "Dockerfile",
    "context": ".."
  },
  "features": {
    "ghcr.io/atsushi11o7/devcontainer-features/base-utils:1": {},
    "ghcr.io/devcontainers/features/node:1": {
      "version": "24"
    }
  },
  "workspaceFolder": "/workspace",
  "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
  "runArgs": [
    "--env-file", "${localWorkspaceFolder}/.env"
  ],
  "mounts": [
    "source=claude-config,target=/root/.claude,type=volume"
  ],
  "containerEnv": {
    "CLAUDE_CONFIG_DIR": "/root/.claude"
  },
  "customizations": {
    "vscode": {
      "extensions": [
        "anthropic.claude-code",
        "ms-python.python",
        "ms-toolsai.jupyter"
      ],
      "settings": {
        "terminal.integrated.defaultProfile.linux": "bash",
        "python.defaultInterpreterPath": "/opt/venv/bin/python"
      }
    }
  },
  "remoteUser": "root"
}

各セクションを順番に解説していきます。


Devcontainer Featuresについて

"features": {
  "ghcr.io/atsushi11o7/devcontainer-features/base-utils:1": {},
  "ghcr.io/devcontainers/features/node:1": {
    "version": "24"
  }
}

GitHub MCPサーバーを含む多くのMCPサーバーは、npxuvxなどのコマンドでプロセスを起動し、標準入出力(stdio)経由でClaude Codeと通信します。npxはNode.jsに付属するパッケージランナーです。つまり、MCPサーバーを使うにはNode.jsが必要です。

PythonやCUDAベースのDockerイメージにはNode.jsが入っていないため、何らかの方法でインストールする必要があります。

Dockerfileに書き込んでもいいのですが、Node.jsはプロジェクト固有ではなく、MCPサーバー起動などに使う汎用ランタイムであるため、Devcontainer Featureで追加しています。

Devcontainer Features とは

Devcontainer Featuresは、Dockerfileで構築したベースイメージの上に、追加のツールや設定を宣言的にインストールできる仕組みです。

「Dockerfileに直接書くのと何が違うの?」と思うかもしれません。主な違いは以下の通りです。

Dockerfileに書く Devcontainer Featuresを使う
記述量 インストール手順を自分で書く 数行の宣言で済む
再利用性 プロジェクトごとにコピペ 複数プロジェクトで使い回しやすい
ベースイメージとの分離 Dockerfileが長くなりがち 関心の分離ができる
バージョン管理 自分でバージョン指定を管理 Feature側でメンテされる

要するに、「Dockerfileはプロジェクト固有の環境構築に集中し、Git・Node.jsなどの汎用ツールはFeaturesに任せる」という役割分担ができます。

今回導入したFeature

ghcr.io/devcontainers/features/node:1 — 公式提供のNode.js Feature

Microsoft/Devcontainersが公式に提供しているFeatureです。versionパラメータでNode.jsのバージョンを指定できます。これにより、コンテナ内でnodeコマンドとnpxコマンドが使えるようになり、MCPサーバーの起動が可能になります。

"ghcr.io/devcontainers/features/node:1": {
  "version": "24"
}

ghcr.io/atsushi11o7/devcontainer-features/base-utils:1 — 自作のFeature

こちらは筆者が自作したDevcontainer Featureです。複数のプロジェクトで共通して使いたいツール(Git、GitHub CLI、基本的なユーティリティなど)を1つのFeatureにまとめています。
今回の記事にはあまり関係ないです。


mounts + containerEnv — Claude Code設定の永続化

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

これを設定しないと、Devcontainerを再作成するたびにClaude Codeの認証がリセットされます。

Claude Codeの設定や認証情報は~/.claudeディレクトリに保存されます。DevcontainerはRebuildすると中身がまっさらになるため、何もしないと毎回/loginからやり直しです。地味にストレスが溜まります。

これを防ぐために、Docker Named Volumeを使って~/.claudeを永続化しています。

コンテナ内の /root/.claude
    ↕ マウント
Docker Named Volume "claude-config"(ホスト側で永続管理)

Named VolumeはDevcontainerを作り直しても消えません。docker volume lsで確認でき、明示的にdocker volume rm claude-configしない限り残り続けます。

containerEnvCLAUDE_CONFIG_DIRは、Claude Codeに設定ディレクトリの場所を明示的に教えるための環境変数です。


runArgs + .env — APIトークンの安全な管理

"runArgs": [
  "--env-file", "${localWorkspaceFolder}/.env"
]

MCPサーバーにはAPIトークンが必要なものもあります。しかし、トークンを.mcp.jsonやDockerfileに直接書くのはセキュリティ上危険です。Git管理下のファイルにトークンをハードコードしてしまうと、リポジトリを公開した瞬間に漏洩します。

そこで、.envファイルにトークンを分離し、Dockerの--env-fileオプションでコンテナに注入する方式を採っています。

.envファイルの作成

プロジェクトルートに.envファイルを作成します。

GITHUB_PERSONAL_ACCESS_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx

必ず.gitignoreに追加してください。

# .gitignore
.env

GitHub Personal Access Tokenの取得

GitHubの Settings → Developer settings → Personal access tokens → Tokens (classic) から発行します。

MCPサーバー用途ではreporead:orgスコープがあれば十分かと思います。

スクリーンショット 2026-03-07 220038.png


customizations — VSCode拡張機能の自動インストール

"customizations": {
  "vscode": {
    "extensions": [
      "anthropic.claude-code",
      "ms-python.python",
      "ms-toolsai.jupyter"
    ],
    "settings": {
      "terminal.integrated.defaultProfile.linux": "bash",
      "python.defaultInterpreterPath": "/opt/venv/bin/python"
    }
  }
}

anthropic.claude-codeを指定しておくと、Devcontainer起動時にClaude CodeのVSCode拡張機能が自動インストールされます。

これにより、ターミナルからのclaudeコマンドに加え、VSCodeのサイドバーからもClaude Codeを利用可能になります。


.mcp.json — MCPサーバーの設定

プロジェクトルートに.mcp.jsonを配置します。Claude Codeはこのファイルを自動検出します。

{
  "mcpServers": {
    "github": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-github"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
      }
    }
  }
}

各キーの意味は以下の通りです。

キー 説明
type "stdio" 標準入出力で通信
command "npx" Node.jsのパッケージランナー(Node.jsが必要な理由
args ["-y", "@modelcontextprotocol/server-github"] -yで確認プロンプトをスキップし、GitHubサーバーパッケージを指定
env ${GITHUB_PERSONAL_ACCESS_TOKEN} .envから注入されたコンテナの環境変数を参照

動作確認

1. Devcontainerの起動

VSCodeでプロジェクトを開き、コマンドパレット(Ctrl+Shift+P)から 「Dev Containers: Rebuild and Reopen in Container」 を実行します。

初回はDockerイメージのビルドとFeaturesのインストールが走るため、少し時間がかかります。

2. Claude Codeの起動

ターミナルでclaudeを実行します。初回は認証が必要なので、表示される指示に従って/loginを行ってください。

スクリーンショット 2026-03-07 231241.png

コンテナ内でClaude Codeが起動した様子。Named Volumeで~/.claudeを永続化しているため、2回目以降のRebuildでは認証不要です。

3. MCPサーバーの認識確認

Claude Code起動時に.mcp.jsonが検出されると、以下のようなプロンプトが表示されます。

スクリーンショット 2026-03-07 231402.png

「New MCP server found in .mcp.json: github」と表示されます。「Use this and all future MCP servers in this project」を選択すると、以降は自動で読み込まれます。

4. MCPサーバーの動作確認

Claude Code内でmcp listと入力すると、接続中のMCPサーバーを確認できます。

スクリーンショット 2026-03-07 231838.png

GitHub MCPサーバーが正常に接続されている状態。

これで環境構築は完了です。Claude Codeに「このリポジトリのIssueを一覧して」「PRを作成して」といった指示が通るようになります。


まとめ

MCPサーバー導入を前提としたDevcontainer + Claude Code環境のポイントをまとめます。

課題 解決策 設定箇所
MCPサーバーの実行にNode.jsが必要 Devcontainer Featureで導入 devcontainer.jsonfeatures
APIトークンを安全に管理したい .env + --env-fileで注入 devcontainer.jsonrunArgs
Rebuild後もClaude Codeの認証を保持 Named Volumeで~/.claudeを永続化 devcontainer.jsonmounts
MCPサーバーの設定 プロジェクトルートに.mcp.jsonを配置 .mcp.json

一度この構成を作ってしまえば、あとは.mcp.jsonにMCPサーバーを追加していくだけで拡張できます。GitHub以外にもさまざまなMCPサーバーが公開されているので、ぜひ試してみてください。

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?