内容
# CodeGraph MCP Docker 多项目远程部署方案
## 目标
将一个父级目录下的多个项目批量构建 CodeGraph 知识库,并通过一个 Docker 容器、一个对外端口提供远程 MCP 访问。
最终访问形态:
```text
http://远程机器:8000/project-a/mcp
http://远程机器:8000/project-b/mcp
http://远程机器:8000/project-c/mcp
```
容器内部仍然为每个项目启动独立的 `codegraph serve --mcp --path <project>`,再由前置 Node 网关按 URL 前缀转发。
## 目录结构
```text
docker/
.env
batch_codegraph_init.sh
codegraph.Dockerfile
docker_codegraph.md
multi_project_gateway.js
codegraph-linux-x64-v1.4.0.tar.gz
install-codegraph.sh
```
说明:
- `docker/codegraph.Dockerfile`:构建 CodeGraph MCP 远程服务镜像。
- `docker/batch_codegraph_init.sh`:扫描项目集合目录下一级子目录,逐个执行 `codegraph init`。
- `docker/multi_project_gateway.js`:扫描已初始化项目,为每个项目启动内部 `supergateway`,并暴露统一 HTTP 入口。
- `docker/.env`:保存构建和运行变量。
- `codegraph-linux-x64-v1.4.0.tar.gz`:CodeGraph Linux x64 离线包,放在仓库根目录作为 Docker build context 的一部分。
## 工作方式
服务端项目集合目录:
```text
/srv/projects/
project-a/
project-b/
project-c/
```
容器内挂载为:
```text
/workspace/projects/
project-a/
project-b/
project-c/
```
批量初始化后:
```text
/workspace/projects/project-a/.codegraph/codegraph.db
/workspace/projects/project-b/.codegraph/codegraph.db
/workspace/projects/project-c/.codegraph/codegraph.db
```
容器启动时,`multi_project_gateway.js` 会:
1. 扫描 `CONTAINER_PROJECTS_PATH` 下一级子目录。
2. 默认只服务存在 `.codegraph/codegraph.db` 的项目。
3. 为每个项目分配内部端口,例如 `9100`、`9101`、`9102`。
4. 启动内部 `supergateway`。
5. 在 `MCP_PORT` 上暴露统一入口。
示例路由:
```text
/project-a/mcp -> 127.0.0.1:9100/mcp
/project-a/healthz -> 127.0.0.1:9100/healthz
/project-b/mcp -> 127.0.0.1:9101/mcp
```
项目 URL slug 由目录名生成。访问根路径或 `/projects` 可以查看实际映射:
```bash
curl "http://远程机器:8000/projects"
```
## 可配置变量
变量集中放在 `docker/.env`:
```dotenv
# Build settings
NODE_IMAGE=node:22-bookworm-slim
APT_MIRROR_BASE=http://mirrors.aliyun.com
CODEGRAPH_VERSION=v1.4.0
CODEGRAPH_ARCHIVE=codegraph-linux-x64-v1.4.0.tar.gz
SUPERGATEWAY_VERSION=3.4.3
IMAGE_NAME=codegraph-mcp
IMAGE_TAG=v1.4.0
IMAGE_TAR=codegraph-mcp-v1.4.0.tar
# Runtime settings
CONTAINER_NAME=codegraph-mcp
HOST_PORT=8000
MCP_PORT=8000
HOST_PROJECTS_PATH=/srv/projects
CONTAINER_PROJECTS_PATH=/workspace/projects
MCP_INTERNAL_PORT_START=9100
STREAMABLE_HTTP_PATH=/mcp
HEALTH_ENDPOINT=/healthz
LOG_LEVEL=info
CODEGRAPH_NO_WATCH=1
CODEGRAPH_EXCLUDE_HIDDEN=1
```
实际部署前通常只需要改:
- `HOST_PROJECTS_PATH`:离线服务器上的项目集合目录。
- `HOST_PORT`:对外暴露端口。
- `IMAGE_TAG` / `IMAGE_TAR`:镜像版本和导出文件名。
- `APT_MIRROR_BASE`:构建镜像时使用的 Debian apt 镜像源。
可选变量:
- `MCP_INTERNAL_PORT_START`:内部 `supergateway` 起始端口,只在容器内使用。
- `CODEGRAPH_EXCLUDE_HIDDEN=1`:跳过隐藏目录。
- `CODEGRAPH_SERVE_UNINITIALIZED=1`:允许服务未初始化目录。默认不建议开启。
## 在线环境构建镜像
在仓库根目录执行。Linux/macOS shell:
```bash
set -a
. docker/.env
set +a
docker build \
-f docker/codegraph.Dockerfile \
--build-arg NODE_IMAGE="${NODE_IMAGE}" \
--build-arg APT_MIRROR_BASE="${APT_MIRROR_BASE}" \
--build-arg CODEGRAPH_VERSION="${CODEGRAPH_VERSION}" \
--build-arg CODEGRAPH_ARCHIVE="${CODEGRAPH_ARCHIVE}" \
--build-arg SUPERGATEWAY_VERSION="${SUPERGATEWAY_VERSION}" \
-t "${IMAGE_NAME}:${IMAGE_TAG}" \
.
```
Windows PowerShell:
```powershell
Get-Content .\docker\.env | Where-Object { $_ -and $_ -notmatch '^#' } | ForEach-Object {
$k, $v = $_ -split '=', 2
Set-Item -Path "Env:$k" -Value $v
}
docker build `
-f .\docker\codegraph.Dockerfile `
--build-arg NODE_IMAGE="$env:NODE_IMAGE" `
--build-arg APT_MIRROR_BASE="$env:APT_MIRROR_BASE" `
--build-arg CODEGRAPH_VERSION="$env:CODEGRAPH_VERSION" `
--build-arg CODEGRAPH_ARCHIVE="$env:CODEGRAPH_ARCHIVE" `
--build-arg SUPERGATEWAY_VERSION="$env:SUPERGATEWAY_VERSION" `
-t "$env:IMAGE_NAME`:$env:IMAGE_TAG" `
.
```
导出镜像:
```bash
docker save "${IMAGE_NAME}:${IMAGE_TAG}" -o "${IMAGE_TAR}"
```
PowerShell:
```powershell
docker save "$env:IMAGE_NAME`:$env:IMAGE_TAG" -o "$env:IMAGE_TAR"
```
## 离线环境加载并运行
加载镜像:
在执行以下指令之前,需要将 .env文件中的HOST_PROJECTS_PATH变量改为真实的项目路径
```bash
set -a
. docker/.env
set +a
docker load -i "${IMAGE_TAR}"
```
运行容器:
```bash
docker run -d \
--name "${CONTAINER_NAME}" \
--env-file docker/.env \
-p "${HOST_PORT}:${MCP_PORT}" \
-v "${HOST_PROJECTS_PATH}:${CONTAINER_PROJECTS_PATH}" \
--restart unless-stopped \
"${IMAGE_NAME}:${IMAGE_TAG}"
```
如果当前用户没有 Docker 权限,在 `docker` 前加 `sudo` 即可。
运行前建议检查:
```bash
printf 'HOST_PROJECTS_PATH=%s\n' "$HOST_PROJECTS_PATH"
printf 'CONTAINER_PROJECTS_PATH=%s\n' "$CONTAINER_PROJECTS_PATH"
printf 'IMAGE=%s:%s\n' "$IMAGE_NAME" "$IMAGE_TAG"
ls -ld "$HOST_PROJECTS_PATH"
```
## 初始化 CodeGraph 索引
容器启动后,对所有一级子项目批量初始化:
```bash
docker exec -it "${CONTAINER_NAME}" batch_codegraph_init.sh "${CONTAINER_PROJECTS_PATH}"
```
初始化完成后重启容器,让前置网关重新扫描已初始化项目,一定要执行这步:
```bash
docker restart "${CONTAINER_NAME}"
```
单个项目也可以手动初始化:
```bash
docker exec -it "${CONTAINER_NAME}" codegraph init "${CONTAINER_PROJECTS_PATH}/project-a"
```
检查状态:
```bash
docker exec -it "${CONTAINER_NAME}" codegraph status "${CONTAINER_PROJECTS_PATH}/project-a"
```
测试查询:
```bash
docker exec -it "${CONTAINER_NAME}" codegraph explore "某个函数名或你的问题" --path "${CONTAINER_PROJECTS_PATH}/project-a"
```
## 远程访问验证
检查统一网关:
```bash
curl "http://远程机器:${HOST_PORT}${HEALTH_ENDPOINT}"
```
查看项目映射:
```bash
curl "http://远程机器:${HOST_PORT}/projects"
```
检查某个项目后端:
```bash
curl "http://远程机器:${HOST_PORT}/project-a/healthz"
```
查看日志:
```bash
docker logs -f "${CONTAINER_NAME}"
```
日志中会出现类似:
```text
[CodeGraph Gateway] project-a -> 127.0.0.1:9100/mcp (/workspace/projects/project-a)
[CodeGraph Gateway] Listening on 0.0.0.0:8000
```
## opencode 配置
opencode 远程 MCP 示例:
```jsonc
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"codegraph-project-a": {
"type": "remote",
"url": "http://远程机器:8000/project-a/mcp",
"enabled": true
},
"codegraph-project-b": {
"type": "remote",
"url": "http://远程机器:8000/project-b/mcp",
"enabled": true
}
}
}
```
实际 `project-a`、`project-b` 以前置网关 `/projects` 返回的 `slug` 为准。
## openclaude 配置
如果当前 OpenClaude 支持 HTTP MCP:
```json
{
"mcpServers": {
"codegraph-project-a": {
"type": "http",
"url": "http://远程机器:8000/project-a/mcp"
}
},
"permissions": {
"allow": [
"mcp__codegraph-project-a__*"
]
}
}
```
如果当前 OpenClaude 不支持 `type: "http"`,使用本地 `mcp-remote`:
```json
{
"mcpServers": {
"codegraph-project-a": {
"type": "stdio",
"command": "node",
"args": [
"D:/LX/Projects/IEI-RAG/codegraph_private/mcp-offline/node_modules/mcp-remote/dist/proxy.js",
"http://远程机器:8000/project-a/mcp",
"--allow-http",
"--transport",
"http-only"
]
}
},
"permissions": {
"allow": [
"mcp__codegraph-project-a__*"
]
}
}
```
## 常见问题
### `/projects` 返回空数组
说明容器启动时没有发现已初始化项目。先执行:
```bash
docker exec -it "${CONTAINER_NAME}" batch_codegraph_init.sh "${CONTAINER_PROJECTS_PATH}"
docker restart "${CONTAINER_NAME}"
```
### 项目目录存在但没有被服务
默认只服务存在 `.codegraph/codegraph.db` 的项目。检查:
```bash
docker exec -it "${CONTAINER_NAME}" ls -l "${CONTAINER_PROJECTS_PATH}/project-a/.codegraph"
```
### 客户端连不上
先检查:
```bash
docker ps
docker logs -f "${CONTAINER_NAME}"
curl "http://远程机器:${HOST_PORT}${HEALTH_ENDPOINT}"
curl "http://远程机器:${HOST_PORT}/projects"
```
再检查防火墙是否开放 `HOST_PORT`。
### Docker 报挂载参数错误
通常是 `.env` 没加载,导致挂载参数为空。检查:
```bash
printf 'HOST_PROJECTS_PATH=%s\n' "$HOST_PROJECTS_PATH"
printf 'CONTAINER_PROJECTS_PATH=%s\n' "$CONTAINER_PROJECTS_PATH"
ls -ld "$HOST_PROJECTS_PATH"
```
### 需要刷新索引
单个项目重新索引:
```bash
docker exec -it "${CONTAINER_NAME}" codegraph index "${CONTAINER_PROJECTS_PATH}/project-a"
```
批量重新索引可以重新执行:
```bash
docker exec -it "${CONTAINER_NAME}" batch_codegraph_init.sh "${CONTAINER_PROJECTS_PATH}"
docker restart "${CONTAINER_NAME}"
```
### 明文 HTTP
内网可直接使用:
```text
http://远程机器:8000/project-a/mcp
```
生产环境建议在前面加 Nginx / TLS:
```text
https://codegraph.example.com/project-a/mcp
```