mirror of
https://github.com/samanhappy/mcphub.git
synced 2025-12-24 02:39:19 -05:00
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
572 lines
11 KiB
Plaintext
572 lines
11 KiB
Plaintext
---
|
||
title: 'Docker 部署'
|
||
description: '使用 Docker 和 Docker Compose 部署 MCPHub'
|
||
---
|
||
|
||
# Docker 部署
|
||
|
||
本指南介绍使用 Docker 部署 MCPHub,包括开发和生产配置。
|
||
|
||
## Docker 快速开始
|
||
|
||
### 使用预构建镜像
|
||
|
||
```bash
|
||
# 拉取最新镜像
|
||
docker pull mcphub/mcphub:latest
|
||
|
||
# 使用默认配置运行
|
||
docker run -d \
|
||
--name mcphub \
|
||
-p 3000:3000 \
|
||
-v $(pwd)/mcp_settings.json:/app/mcp_settings.json \
|
||
mcphub/mcphub:latest
|
||
```
|
||
|
||
### 从源码构建
|
||
|
||
```bash
|
||
# 克隆仓库
|
||
git clone https://github.com/your-username/mcphub.git
|
||
cd mcphub
|
||
|
||
# 构建 Docker 镜像
|
||
docker build -t mcphub:local .
|
||
|
||
# 运行容器
|
||
docker run -d \
|
||
--name mcphub \
|
||
-p 3000:3000 \
|
||
-v $(pwd)/mcp_settings.json:/app/mcp_settings.json \
|
||
mcphub:local
|
||
```
|
||
|
||
### 构建扩展功能版本
|
||
|
||
Docker 镜像支持 `INSTALL_EXT` 构建参数以包含额外工具:
|
||
|
||
```bash
|
||
# 构建扩展功能版本(包含 Docker CLI、Chrome/Playwright)
|
||
docker build --build-arg INSTALL_EXT=true -t mcphub:extended .
|
||
|
||
# 运行容器并挂载 Docker socket(用于 Docker-in-Docker 工作流)
|
||
docker run -d \
|
||
--name mcphub \
|
||
-p 3000:3000 \
|
||
-v $(pwd)/mcp_settings.json:/app/mcp_settings.json \
|
||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||
mcphub:extended
|
||
|
||
# 验证 Docker CLI 可用
|
||
docker exec mcphub docker --version
|
||
```
|
||
|
||
<Note>
|
||
**INSTALL_EXT=true 包含的功能:**
|
||
- **Docker CLI**:用于容器管理和基于 Docker 的工作流
|
||
- **Chrome/Playwright**(仅 amd64):用于浏览器自动化任务
|
||
|
||
扩展镜像较大,但为高级用例提供了额外功能。
|
||
</Note>
|
||
|
||
<Warning>
|
||
挂载 Docker socket(`/var/run/docker.sock`)时,容器将获得访问主机 Docker 守护进程的权限。仅在可信环境中使用此功能。
|
||
</Warning>
|
||
|
||
## Docker Compose 设置
|
||
|
||
### 基本配置
|
||
|
||
创建 `docker-compose.yml` 文件:
|
||
|
||
```yaml
|
||
version: '3.8'
|
||
|
||
services:
|
||
mcphub:
|
||
image: mcphub/mcphub:latest
|
||
# 本地开发时使用:
|
||
# build: .
|
||
container_name: mcphub
|
||
ports:
|
||
- '3000:3000'
|
||
environment:
|
||
- NODE_ENV=production
|
||
- PORT=3000
|
||
- JWT_SECRET=${JWT_SECRET:-your-jwt-secret}
|
||
- DATABASE_URL=postgresql://mcphub:password@postgres:5432/mcphub
|
||
volumes:
|
||
- ./mcp_settings.json:/app/mcp_settings.json:ro
|
||
- ./servers.json:/app/servers.json:ro
|
||
- mcphub_data:/app/data
|
||
depends_on:
|
||
postgres:
|
||
condition: service_healthy
|
||
restart: unless-stopped
|
||
networks:
|
||
- mcphub-network
|
||
|
||
postgres:
|
||
image: postgres:15-alpine
|
||
container_name: mcphub-postgres
|
||
environment:
|
||
- POSTGRES_DB=mcphub
|
||
- POSTGRES_USER=mcphub
|
||
- POSTGRES_PASSWORD=password
|
||
volumes:
|
||
- postgres_data:/var/lib/postgresql/data
|
||
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql:ro
|
||
ports:
|
||
- '5432:5432'
|
||
healthcheck:
|
||
test: ['CMD-SHELL', 'pg_isready -U mcphub -d mcphub']
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 5
|
||
restart: unless-stopped
|
||
networks:
|
||
- mcphub-network
|
||
|
||
volumes:
|
||
postgres_data:
|
||
mcphub_data:
|
||
|
||
networks:
|
||
mcphub-network:
|
||
driver: bridge
|
||
```
|
||
|
||
### 生产配置(包含 Nginx)
|
||
|
||
```yaml
|
||
version: '3.8'
|
||
|
||
services:
|
||
nginx:
|
||
image: nginx:alpine
|
||
container_name: mcphub-nginx
|
||
ports:
|
||
- '80:80'
|
||
- '443:443'
|
||
volumes:
|
||
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||
- ./ssl:/etc/nginx/ssl:ro
|
||
- nginx_logs:/var/log/nginx
|
||
depends_on:
|
||
- mcphub
|
||
restart: unless-stopped
|
||
networks:
|
||
- mcphub-network
|
||
|
||
mcphub:
|
||
image: mcphub/mcphub:latest
|
||
container_name: mcphub-app
|
||
expose:
|
||
- '3000'
|
||
environment:
|
||
- NODE_ENV=production
|
||
- PORT=3000
|
||
- JWT_SECRET=${JWT_SECRET}
|
||
- JWT_EXPIRES_IN=${JWT_EXPIRES_IN:-24h}
|
||
- DATABASE_URL=postgresql://mcphub:${POSTGRES_PASSWORD}@postgres:5432/mcphub
|
||
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
||
- REDIS_URL=redis://redis:6379
|
||
volumes:
|
||
- ./mcp_settings.json:/app/mcp_settings.json:ro
|
||
- ./servers.json:/app/servers.json:ro
|
||
- mcphub_data:/app/data
|
||
- mcphub_logs:/app/logs
|
||
depends_on:
|
||
postgres:
|
||
condition: service_healthy
|
||
redis:
|
||
condition: service_healthy
|
||
restart: unless-stopped
|
||
networks:
|
||
- mcphub-network
|
||
healthcheck:
|
||
test: ['CMD', 'wget', '--quiet', '--tries=1', '--spider', 'http://localhost:3000/health']
|
||
interval: 30s
|
||
timeout: 10s
|
||
retries: 3
|
||
|
||
postgres:
|
||
image: postgres:15-alpine
|
||
container_name: mcphub-postgres
|
||
environment:
|
||
- POSTGRES_DB=mcphub
|
||
- POSTGRES_USER=mcphub
|
||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||
volumes:
|
||
- postgres_data:/var/lib/postgresql/data
|
||
- ./backups:/backups
|
||
healthcheck:
|
||
test: ['CMD-SHELL', 'pg_isready -U mcphub -d mcphub']
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 5
|
||
restart: unless-stopped
|
||
networks:
|
||
- mcphub-network
|
||
|
||
redis:
|
||
image: redis:7-alpine
|
||
container_name: mcphub-redis
|
||
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
|
||
volumes:
|
||
- redis_data:/data
|
||
healthcheck:
|
||
test: ['CMD', 'redis-cli', 'ping']
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 5
|
||
restart: unless-stopped
|
||
networks:
|
||
- mcphub-network
|
||
|
||
volumes:
|
||
postgres_data:
|
||
redis_data:
|
||
mcphub_data:
|
||
mcphub_logs:
|
||
nginx_logs:
|
||
|
||
networks:
|
||
mcphub-network:
|
||
driver: bridge
|
||
```
|
||
|
||
### 环境变量
|
||
|
||
为 Docker Compose 创建 `.env` 文件:
|
||
|
||
```env
|
||
# 应用程序
|
||
NODE_ENV=production
|
||
JWT_SECRET=your-super-secret-jwt-key-change-this
|
||
JWT_EXPIRES_IN=24h
|
||
|
||
# 数据库
|
||
POSTGRES_PASSWORD=your-secure-database-password
|
||
|
||
# Redis
|
||
REDIS_PASSWORD=your-secure-redis-password
|
||
|
||
# 外部 API
|
||
OPENAI_API_KEY=your-openai-api-key
|
||
|
||
# 可选:自定义端口
|
||
# PORT=3000
|
||
```
|
||
|
||
## 开发设置
|
||
|
||
### 开发 Docker Compose
|
||
|
||
创建 `docker-compose.dev.yml`:
|
||
|
||
```yaml
|
||
version: '3.8'
|
||
|
||
services:
|
||
mcphub-dev:
|
||
build:
|
||
context: .
|
||
dockerfile: Dockerfile.dev
|
||
container_name: mcphub-dev
|
||
ports:
|
||
- '3000:3000'
|
||
- '5173:5173' # 前端开发服务器
|
||
- '9229:9229' # 调试端口
|
||
environment:
|
||
- NODE_ENV=development
|
||
- PORT=3000
|
||
- DATABASE_URL=postgresql://mcphub:password@postgres:5432/mcphub
|
||
volumes:
|
||
- .:/app
|
||
- /app/node_modules
|
||
- /app/frontend/node_modules
|
||
depends_on:
|
||
- postgres
|
||
command: pnpm dev
|
||
networks:
|
||
- mcphub-dev
|
||
|
||
postgres:
|
||
image: postgres:15-alpine
|
||
container_name: mcphub-postgres-dev
|
||
environment:
|
||
- POSTGRES_DB=mcphub
|
||
- POSTGRES_USER=mcphub
|
||
- POSTGRES_PASSWORD=password
|
||
ports:
|
||
- '5432:5432'
|
||
volumes:
|
||
- postgres_dev_data:/var/lib/postgresql/data
|
||
networks:
|
||
- mcphub-dev
|
||
|
||
volumes:
|
||
postgres_dev_data:
|
||
|
||
networks:
|
||
mcphub-dev:
|
||
driver: bridge
|
||
```
|
||
|
||
### 开发 Dockerfile
|
||
|
||
创建 `Dockerfile.dev`:
|
||
|
||
```dockerfile
|
||
FROM node:20-alpine
|
||
|
||
# 安装 pnpm
|
||
RUN npm install -g pnpm
|
||
|
||
# 设置工作目录
|
||
WORKDIR /app
|
||
|
||
# 复制包文件
|
||
COPY package.json pnpm-lock.yaml ./
|
||
COPY frontend/package.json ./frontend/
|
||
|
||
# 安装依赖
|
||
RUN pnpm install
|
||
|
||
# 复制源代码
|
||
COPY . .
|
||
|
||
# 暴露端口
|
||
EXPOSE 3000 5173 9229
|
||
|
||
# 启动开发服务器
|
||
CMD ["pnpm", "dev"]
|
||
```
|
||
|
||
## 运行应用程序
|
||
|
||
### 开发模式
|
||
|
||
```bash
|
||
# 启动开发环境
|
||
docker-compose -f docker-compose.dev.yml up -d
|
||
|
||
# 查看日志
|
||
docker-compose -f docker-compose.dev.yml logs -f mcphub-dev
|
||
|
||
# 停止开发环境
|
||
docker-compose -f docker-compose.dev.yml down
|
||
```
|
||
|
||
### 生产模式
|
||
|
||
```bash
|
||
# 启动生产环境
|
||
docker-compose up -d
|
||
|
||
# 查看日志
|
||
docker-compose logs -f mcphub
|
||
|
||
# 停止生产环境
|
||
docker-compose down
|
||
```
|
||
|
||
## 配置管理
|
||
|
||
### MCP 设置卷挂载
|
||
|
||
创建您的 `mcp_settings.json`:
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"fetch": {
|
||
"command": "uvx",
|
||
"args": ["mcp-server-fetch"]
|
||
},
|
||
"playwright": {
|
||
"command": "npx",
|
||
"args": ["@playwright/mcp@latest", "--headless"]
|
||
},
|
||
"amap": {
|
||
"command": "npx",
|
||
"args": ["-y", "@amap/amap-maps-mcp-server"],
|
||
"env": {
|
||
"AMAP_MAPS_API_KEY": "your-api-key"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 密钥管理
|
||
|
||
对于生产环境,使用 Docker 密钥:
|
||
|
||
```yaml
|
||
version: '3.8'
|
||
|
||
services:
|
||
mcphub:
|
||
image: mcphub/mcphub:latest
|
||
environment:
|
||
- JWT_SECRET_FILE=/run/secrets/jwt_secret
|
||
- DATABASE_PASSWORD_FILE=/run/secrets/db_password
|
||
secrets:
|
||
- jwt_secret
|
||
- db_password
|
||
|
||
secrets:
|
||
jwt_secret:
|
||
file: ./secrets/jwt_secret.txt
|
||
db_password:
|
||
file: ./secrets/db_password.txt
|
||
```
|
||
|
||
## 数据持久化
|
||
|
||
### 数据库备份
|
||
|
||
在 `docker-compose.yml` 中添加备份服务:
|
||
|
||
```yaml
|
||
services:
|
||
backup:
|
||
image: postgres:15-alpine
|
||
container_name: mcphub-backup
|
||
environment:
|
||
- PGPASSWORD=${POSTGRES_PASSWORD}
|
||
volumes:
|
||
- ./backups:/backups
|
||
- ./scripts/backup.sh:/backup.sh:ro
|
||
command: /bin/sh -c "chmod +x /backup.sh && /backup.sh"
|
||
depends_on:
|
||
- postgres
|
||
profiles:
|
||
- backup
|
||
networks:
|
||
- mcphub-network
|
||
```
|
||
|
||
创建 `scripts/backup.sh`:
|
||
|
||
```bash
|
||
#!/bin/sh
|
||
BACKUP_FILE="/backups/mcphub_$(date +%Y%m%d_%H%M%S).sql"
|
||
pg_dump -h postgres -U mcphub -d mcphub > "$BACKUP_FILE"
|
||
echo "备份已创建:$BACKUP_FILE"
|
||
|
||
# 只保留最近 7 天的备份
|
||
find /backups -name "mcphub_*.sql" -mtime +7 -delete
|
||
```
|
||
|
||
运行备份:
|
||
|
||
```bash
|
||
docker-compose --profile backup run --rm backup
|
||
```
|
||
|
||
## 监控和健康检查
|
||
|
||
### 健康检查端点
|
||
|
||
在您的应用程序中添加:
|
||
|
||
```javascript
|
||
// 在您的 Express 应用中
|
||
app.get('/health', (req, res) => {
|
||
res.json({
|
||
status: 'healthy',
|
||
timestamp: new Date().toISOString(),
|
||
uptime: process.uptime(),
|
||
memory: process.memoryUsage(),
|
||
version: process.env.npm_package_version,
|
||
});
|
||
});
|
||
```
|
||
|
||
### Docker 健康检查
|
||
|
||
```yaml
|
||
services:
|
||
mcphub:
|
||
# ... 其他配置
|
||
healthcheck:
|
||
test: ['CMD', 'wget', '--quiet', '--tries=1', '--spider', 'http://localhost:3000/health']
|
||
interval: 30s
|
||
timeout: 10s
|
||
retries: 3
|
||
start_period: 60s
|
||
```
|
||
|
||
### 使用 Watchtower 监控
|
||
|
||
添加自动更新:
|
||
|
||
```yaml
|
||
services:
|
||
watchtower:
|
||
image: containrrr/watchtower
|
||
container_name: mcphub-watchtower
|
||
volumes:
|
||
- /var/run/docker.sock:/var/run/docker.sock
|
||
environment:
|
||
- WATCHTOWER_CLEANUP=true
|
||
- WATCHTOWER_POLL_INTERVAL=3600
|
||
- WATCHTOWER_INCLUDE_STOPPED=true
|
||
restart: unless-stopped
|
||
```
|
||
|
||
## 故障排除
|
||
|
||
### 常见问题
|
||
|
||
**容器启动失败**:使用 `docker-compose logs mcphub` 检查日志
|
||
|
||
**数据库连接错误**:确保 PostgreSQL 健康且可访问
|
||
|
||
**端口冲突**:检查端口 3000/5432 是否已被占用
|
||
|
||
**卷挂载问题**:验证文件路径和权限
|
||
|
||
### 调试命令
|
||
|
||
```bash
|
||
# 检查容器状态
|
||
docker-compose ps
|
||
|
||
# 查看日志
|
||
docker-compose logs -f [service_name]
|
||
|
||
# 在容器中执行命令
|
||
docker-compose exec mcphub sh
|
||
|
||
# 检查数据库连接
|
||
docker-compose exec postgres psql -U mcphub -d mcphub
|
||
|
||
# 重启特定服务
|
||
docker-compose restart mcphub
|
||
|
||
# 重新构建并重启
|
||
docker-compose up --build -d
|
||
```
|
||
|
||
### 性能优化
|
||
|
||
```yaml
|
||
services:
|
||
mcphub:
|
||
# ... 其他配置
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
memory: 512M
|
||
cpus: '0.5'
|
||
reservations:
|
||
memory: 256M
|
||
cpus: '0.25'
|
||
```
|
||
|
||
此 Docker 设置为 MCPHub 提供了完整的容器化环境,包含开发和生产配置。
|