使用 Docker 和 Docker Compose 部署 MCPHub
# 拉取最新镜像
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
# 克隆仓库
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-compose.yml
文件:
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
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
.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.dev.yml
:
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.dev
:
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"]
# 启动开发环境
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
# 启动生产环境
docker-compose up -d
# 查看日志
docker-compose logs -f mcphub
# 停止生产环境
docker-compose down
mcp_settings.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"
}
}
}
}
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
中添加备份服务:
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
:
#!/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
docker-compose --profile backup run --rm backup
// 在您的 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,
});
});
services:
mcphub:
# ... 其他配置
healthcheck:
test: ['CMD', 'wget', '--quiet', '--tries=1', '--spider', 'http://localhost:3000/health']
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
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 是否已被占用
卷挂载问题:验证文件路径和权限
# 检查容器状态
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
services:
mcphub:
# ... 其他配置
deploy:
resources:
limits:
memory: 512M
cpus: '0.5'
reservations:
memory: 256M
cpus: '0.25'