はじめに
この記事は、QiitaのModel Context Protocol(以下、MCP)解説シリーズの第22回です。
今回は、これまでに作成したMCPサーバーを本格的に運用するための第一歩として、Dockerを使った配布方法を解説します。Dockerを使うことで、環境の違いによる問題を解決し、誰でも簡単にMCPサーバーを動かせるようになります。
💡 なぜDockerが必要なのか?
「私の環境では動くのに、他の人の環境では動かない…」これは、開発者がよく直面する問題です。OS、ライブラリのバージョン、依存関係の違いが原因で、アプリケーションの動作が不安定になることがあります。
MCPサーバーにおいても同様の問題が発生します。特に以下のような課題があります:
- Node.jsバージョンの違い: TypeScriptやESモジュールの対応状況が異なる
- 依存パッケージの競合: 異なるプロジェクトで使用するライブラリバージョンの衝突
- システム固有の設定: 環境変数やファイルパスの違い
Dockerは、コンテナという仮想的な環境にアプリケーションと必要な依存関係をすべて詰め込みます。これにより、以下のメリットが得られます:
- 環境の一貫性: 開発環境、テスト環境、本番環境のすべてで、全く同じ環境でアプリケーションを動かせます
- 配布の簡便性: Dockerイメージを配布するだけで、受け取った側はDockerをインストールするだけでアプリケーションを動かせます
- 分離と安全性: 各コンテナは独立しているため、他のアプリケーションに影響を与えません
📝 ステップ1:MCPサーバー用Dockerfileの作成
MCPサーバーは、Claudeとstdio(標準入出力)で通信する特殊なアプリケーションです。通常のWebサーバーとは異なり、HTTPポートを開く必要がありません。
プロジェクトのルートディレクトリに、Dockerfileというファイルを作成し、以下の内容を記述してください:
# 1. ベースイメージの指定
# Node.js 20の軽量版であるalpineイメージを使用
FROM node:20-alpine
# 2. 作業ディレクトリの設定
# コンテナ内で作業するディレクトリを/appに設定
WORKDIR /app
# 3. 依存関係のインストール
# package.jsonとpackage-lock.jsonをコピー
COPY package*.json ./
# npm installを実行して依存関係をインストール
RUN npm ci --only=production
# 4. アプリケーションファイルのコピー
# 必要なファイルのみをコンテナにコピー
COPY src/ ./src/
COPY tsconfig.json ./
# 5. TypeScriptのトランスパイル
# 本番環境用にJavaScriptに変換
RUN npm install -g typescript && \
npx tsc && \
npm uninstall -g typescript
# 6. 不要なファイルを削除してイメージサイズを最適化
RUN rm -rf src/ tsconfig.json node_modules/typescript
# 7. 実行時のユーザーを設定(セキュリティ向上)
USER node
# 8. MCPサーバーの起動コマンド
# MCPサーバーはstdioで通信するため、特別なオプションが必要
CMD ["node", "dist/index.js"]
📝 ステップ2:MCP用package.jsonの調整
MCPサーバー用のpackage.jsonを適切に設定します:
{
"name": "my-mcp-server",
"version": "1.0.0",
"description": "My MCP Server with Docker support",
"type": "module",
"main": "dist/index.js",
"scripts": {
"start": "node dist/index.js",
"dev": "tsx src/index.ts",
"build": "tsc",
"clean": "rm -rf dist"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^0.4.0"
},
"devDependencies": {
"tsx": "^4.7.0",
"typescript": "^5.3.0",
"@types/node": "^20.0.0"
},
"engines": {
"node": ">=18.0.0"
}
}
📝 ステップ3:.dockerignoreファイルの作成
Dockerビルド時に不要なファイルを除外するため、.dockerignoreファイルを作成します:
node_modules
dist
.git
.gitignore
README.md
Dockerfile
.dockerignore
*.log
.env.local
.env.*.local
🚀 ステップ4:Dockerイメージのビルドと配布
1. Dockerイメージのビルド
# イメージをビルド
docker build -t my-mcp-server:latest .
# マルチステージビルドでサイズ最適化(オプション)
docker build -t my-mcp-server:latest --target production .
2. MCPサーバーの実行とテスト
MCPサーバーは直接実行するものではなく、Claudeから呼び出されます。テストのために、以下のようにコンテナ内でサーバーが正常に起動することを確認できます:
# コンテナ内でMCPサーバーを起動してテスト
docker run --rm -it my-mcp-server:latest node -e "
const server = require('./dist/index.js');
console.log('MCP Server loaded successfully');
process.exit(0);
"
3. Claude Desktop用の設定
作成したDockerイメージをClaude Desktopで使用するには、claude_desktop_config.jsonでDocker経由でサーバーを起動するよう設定します:
{
"mcpServers": {
"my-docker-mcp-server": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"--init",
"my-mcp-server:latest"
]
}
}
}
📦 ステップ5:Docker Hubへの配布
1. Docker Hubにプッシュ
# Docker Hubにログイン
docker login
# イメージにタグを付ける
docker tag my-mcp-server:latest yourusername/my-mcp-server:latest
docker tag my-mcp-server:latest yourusername/my-mcp-server:v1.0.0
# Docker Hubにプッシュ
docker push yourusername/my-mcp-server:latest
docker push yourusername/my-mcp-server:v1.0.0
2. 使用者向けの設定例
他のユーザーは以下の設定でMCPサーバーを使用できます:
{
"mcpServers": {
"shared-mcp-server": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"--init",
"yourusername/my-mcp-server:latest"
]
}
}
}
🔧 高度な設定
環境変数の渡し方
{
"mcpServers": {
"my-mcp-server": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"--init",
"-e", "API_KEY=your_api_key",
"-e", "DEBUG=true",
"my-mcp-server:latest"
]
}
}
}
ボリュームマウント
ファイルへのアクセスが必要な場合:
{
"mcpServers": {
"file-access-mcp": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"--init",
"-v", "/path/to/data:/app/data:ro",
"my-mcp-server:latest"
]
}
}
}
🎯 まとめ
Dockerを使うことで、MCPサーバーを環境に依存しないポータブルなアプリケーションとして配布できます。
重要なポイント:
- Dockerfile: MCPサーバー特有の要件(stdio通信)を考慮した設計
- Dockerイメージ: アプリケーションと依存関係を一つにまとめたパッケージ
- Claude Desktop設定: Docker経由でMCPサーバーを起動する設定方法
セキュリティのベストプラクティス:
- 本番用イメージでは非rootユーザーで実行
- 不要なパッケージは削除してイメージサイズを最小化
- 機密情報は環境変数経由で渡す
このDockerベースの配布方法により、MCPサーバーの共有と再利用が格段に容易になります。GitHub ActionsのようなCI/CDパイプラインと組み合わせることで、自動的なビルドとデプロイも実現できます。
次回は、本番運用で最も重要なテーマの一つ、セキュリティとアクセス制御について解説します。お楽しみに!