> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mcphub.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Docker 部署

> 使用 Docker 和 Docker Compose 部署 MCPHub

# Docker 部署

本指南介绍使用 Docker 部署 MCPHub，包括开发和生产配置。

## Docker 快速开始

### 使用预构建镜像

标准 MCPHub 镜像内置 Node.js/pnpm、Python、uv/uvx、Git 和构建工具。如果需要为 Rust MCP server 使用 Cargo 和稳定版 Rust 工具链，请使用 `latest-full` 镜像。

```bash theme={null}
# 拉取最新镜像
docker pull samanhappy/mcphub:latest

# 使用默认配置运行
docker run -d \
  --name mcphub \
  -p 3000:3000 \
  -v ./data:/app/data \
  samanhappy/mcphub:latest
```

镜像默认使用 `/app/data/mcp_settings.json`。挂载整个数据目录可持久化配置、用户、凭据绑定及其加密密钥。如需自定义服务器，可在首次启动前创建 `data/mcp_settings.json`，或在启动后编辑现有文件。后台运行（`-d`）时，通过 `docker logs mcphub` 查看首次生成的管理员密码。

启动时会自动识别旧方式挂载的 `/app/mcp_settings.json`，并优先于数据目录使用，因此原有 Docker 命令无需修改。显式设置的 `MCPHUB_SETTING_PATH` 始终拥有最高优先级。为完整持久化数据，应将配置文件及已有的 `.credentials.json`、`.credentials.key` 伴随文件一起迁入挂载的数据目录。仍支持显式覆盖 `MCPHUB_SETTING_PATH`。

### 从源码构建

```bash theme={null}
# 克隆仓库
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 ./data:/app/data \
  mcphub:local
```

### 构建扩展功能版本

Docker 镜像支持 `INSTALL_EXT` 构建参数以包含额外工具。发布的 `-full` 镜像会启用此参数：

```bash theme={null}
# 构建扩展功能版本（包含稳定版 Rust/Cargo、Docker 引擎，以及供 Playwright 使用的 Chrome 和 Firefox）
docker build --build-arg INSTALL_EXT=true -t mcphub:extended .

# 方式 1: 使用自动 Docker-in-Docker（需要特权模式）
docker run -d \
  --name mcphub \
  --privileged \
  -p 3000:3000 \
  -v ./data:/app/data \
  mcphub:extended

# 方式 2: 挂载 Docker socket（使用宿主机的 Docker 守护进程）
docker run -d \
  --name mcphub \
  -p 3000:3000 \
  -v ./data:/app/data \
  -v /var/run/docker.sock:/var/run/docker.sock \
  mcphub:extended

# 验证 Docker 可用
docker exec mcphub docker --version
docker exec mcphub docker ps
```

<Note>
  **INSTALL\_EXT=true 包含的功能：**

  * **稳定版 Rust + Cargo**：通过 rustup 安装，用于基于 Rust 的 MCP server。
  * **Docker 引擎**：完整的 Docker 守护进程和 CLI，用于容器管理。在特权模式下运行时，守护进程会自动启动。
  * **Chrome + Firefox（供 Playwright 使用，仅 amd64）**：用于浏览器自动化任务

  扩展镜像较大，但为高级用例提供了额外功能。
</Note>

<Warning>
  **Docker-in-Docker 安全注意事项：**

  * **特权模式**（`--privileged`）：容器内启动 Docker 守护进程需要此权限。这会授予容器在宿主机上的提升权限。
  * **Docker socket 挂载**（`/var/run/docker.sock`）：使容器可以访问宿主机的 Docker 守护进程。两种方式都应仅在可信环境中使用。
  * 生产环境建议使用 Docker socket 挂载而非特权模式，以提高安全性。
</Warning>

## Docker Compose 设置

### 基本配置

创建 `docker-compose.yml` 文件：

```yaml theme={null}
version: '3.8'

services:
  mcphub:
    image: samanhappy/mcphub:latest
    # 本地开发时使用：
    # build: .
    container_name: mcphub
    ports:
      - '3000:3000'
    environment:
      - NODE_ENV=production
      - PORT=3000
      - JWT_SECRET=${JWT_SECRET:-your-jwt-secret}
      - DB_URL=postgresql://mcphub:password@postgres:5432/mcphub
    volumes:
      - ./servers.json:/app/servers.json:ro
      - ./data:/app/data
      # 让已安装的 stdio 服务器包在容器重建后依然保留。
      # 参见下方"持久化 stdio 包缓存"。
      - mcphub_npm_cache:/root/.npm
      - mcphub_uv_cache:/root/.cache/uv
    depends_on:
      postgres:
        condition: service_healthy
    restart: unless-stopped
    networks:
      - mcphub-network

  postgres:
    image: pgvector/pgvector:pg17
    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_npm_cache:
  mcphub_uv_cache:

networks:
  mcphub-network:
    driver: bridge
```

### 持久化 stdio 包缓存

`stdio` 服务器在首次使用时会下载并安装对应的包：`npx` 使用 npm 的缓存，`uvx` 以及其他基于
`uv` 的命令使用 uv 的缓存。镜像未设置 `USER`，因此以 `root` 运行，这些安装内容位于：

| 路径 | 存放内容 |
| - | - |
| `/root/.npm/_npx` | `npx` 安装的包 |
| `/root/.npm/_cacache` | npm 下载的 tarball |
| `/root/.cache/uv` | uv 的下载缓存，以及 `uvx` 创建的环境 |

`uv tool install` 创建的环境位于 `~/.local/share/uv/tools`，它们烘焙在镜像层中，不受这里的
讨论影响。如果你以非 root 用户运行镜像，`~` 就不是 `/root`：上表中的路径与下文的挂载目标都需
要改成该用户的家目录。

这些路径默认都不是卷，因此只存在于容器的可写层。而可写层会在容器被**重建**时丢弃——升级镜像、
执行 `docker compose down && up -d`，或修改任何服务配置都会触发重建。下次启动时，所有
`stdio` 服务器会同时从零重新安装，之后才能开始各自的 MCP 握手。

<Warning>
  `docker restart` 保留可写层，因此不会丢失缓存；而 `docker compose down` 后再 `up -d`
  会删除并重建容器，缓存随之消失。如果你发现"重启后似乎重装了所有东西"，通常就是这个区别。
</Warning>

把这两个路径挂载出来，安装内容就会保存在宿主机上：

```yaml theme={null}
services:
  mcphub:
    volumes:
      - mcphub_npm_cache:/root/.npm
      - mcphub_uv_cache:/root/.cache/uv

volumes:
  mcphub_npm_cache:
  mcphub_uv_cache:
```

具名卷可以在 `docker compose down` 后保留，只有 `down -v` 才会删除。绑定挂载
（`./data/npm-cache:/root/.npm`）同样可行，也更方便手动查看或清理，但它不会像具名卷那样用镜像
中该路径的内容初始化——而是直接遮蔽掉镜像里已有的东西。在 amd64 上，`-full` 镜像会在 `/root/.npm/_npx`
中预装 Playwright，因此在该路径使用绑定挂载意味着要重新下载一次。

几点值得注意：

* **不需要锁定版本。** 未指定版本的 `npx -y <package>` 会直接复用缓存中已安装的包，而不会重新
  安装。但 npm 每次运行仍会向 registry 重新校验包的元数据，因此 registry（或你的代理）必须保持
  可达——缓存省下的是安装成本，不是这一次网络往返。
* **挂载后的第一次启动仍然是冷的。** 卷刚创建时是空的，这一次需要付出完整的安装成本；此后每次
  重建都会复用它。
* **预留足够空间。** 约 90 个 `stdio` 服务器大致占用 2 GB。
* **安装内容损坏时**，请使用该服务器的「重新安装」操作——仅 `npx` 与 `uvx` 服务器支持。对
  `uvx` 而言，它只刷新那一个包（在下次启动时注入 `--refresh` 参数）；对 `npx` 而言，它会删除
  整个共用的 `/root/.npm/_npx` 目录，因此下次启动时**所有** npx 服务器都会重新安装，而不只是
  你指定的那一个。`_cacache` 卷的作用就是让这次重装的代价变小。

规模越大影响越明显。在一个约 95 个 `stdio` 服务器的部署中，冷启动重建后只有 19 个连接成功，
74 个因 `MCP error -32001: Request timed out` 连接失败，因为所有服务器都在同时安装、互相争抢
资源。挂载缓存后，同一次重启达到 73 个连接成功且没有任何超时——但那次运行同时把 `INIT_TIMEOUT`
从默认的 300000 提高到了 900000，所以这两项改动必须分开看。按每分钟的连接曲线粗略拆分：缓存在
原本 300 秒的预算内约值 +45 台，更长的超时约值 +9 台。主要成本是重新安装包，而不是等待。

### 生产配置（包含 Nginx）

```yaml theme={null}
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: samanhappy/mcphub:latest
    container_name: mcphub-app
    expose:
      - '3000'
    environment:
      - NODE_ENV=production
      - PORT=3000
      - JWT_SECRET=${JWT_SECRET}
      - DB_URL=postgresql://mcphub:${POSTGRES_PASSWORD}@postgres:5432/mcphub
      - OPENAI_API_KEY=${OPENAI_API_KEY}
      - REDIS_URL=redis://redis:6379
    volumes:
      - ./servers.json:/app/servers.json:ro
      - ./data:/app/data
      - mcphub_logs:/app/logs
      - mcphub_npm_cache:/root/.npm
      - mcphub_uv_cache:/root/.cache/uv
    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: pgvector/pgvector:pg17
    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_logs:
  mcphub_npm_cache:
  mcphub_uv_cache:
  nginx_logs:

networks:
  mcphub-network:
    driver: bridge
```

### 环境变量

为 Docker Compose 创建 `.env` 文件：

```env theme={null}
# 应用程序
NODE_ENV=production
JWT_SECRET=your-super-secret-jwt-key-change-this

# 数据库
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 theme={null}
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
      - DB_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: pgvector/pgvector:pg17
    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 theme={null}
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 theme={null}
# 启动开发环境
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 theme={null}
# 启动生产环境
docker-compose up -d

# 查看日志
docker-compose logs -f mcphub

# 停止生产环境
docker-compose down
```

## 配置管理

### MCP 设置卷挂载

首次启动前，创建 `data/mcp_settings.json`：

```json theme={null}
{
  "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 theme={null}
version: '3.8'

services:
  mcphub:
    image: samanhappy/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 theme={null}
services:
  backup:
    image: pgvector/pgvector:pg17
    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 theme={null}
#!/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 theme={null}
docker-compose --profile backup run --rm backup
```

## 监控和健康检查

### 健康检查端点

在您的应用程序中添加：

```javascript theme={null}
// 在您的 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 theme={null}
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 theme={null}
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 theme={null}
# 检查容器状态
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 theme={null}
services:
  mcphub:
    # ... 其他配置
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '0.5'
        reservations:
          memory: 256M
          cpus: '0.25'
```

此 Docker 设置为 MCPHub 提供了完整的容器化环境，包含开发和生产配置。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.