Docker构建和部署指南(mcpo项目)
感谢@BigUncle的pull请求
本指南系统地概述了Docker容器环境中mcpo项目的构建、部署、故障排除和最佳实践,反映了项目的当前状态。
一、项目概况及架构
该项目使用Docker和Docker Compose进行容器化部署 mcpo (模型上下文协议OpenAPI代理)。核心设计原则包括:
- 动态依赖安装:在容器启动时
start.sh脚本读取config.json并动态安装所需的Python(uvx)Node.js(npx)基于定义的工具mcpServers. - 非根用户执行:容器最终以非root用户身份运行
appuser以增强安全性。 - 依赖性和数据持久性:通过Docker Compose卷挂载、配置、日志、数据和缓存目录
uv和npm被持久化到主机。 - 灵活的源配置:支持动态配置
pip通过构建参数获取来源(PIP_SOURCE),默认使用阿里云镜像加速apt. - 环境隔离:In
start.sh,每个MCP工具安装都发生在一个子shell中,以避免环境变量冲突。
二、构建和部署过程
1.环境准备
-
Docker&Docker编写:推荐使用Docker 24+和Docker Compose 2.x。
-
.env文件:创建一个.env项目根目录中的文件,用于敏感信息和配置。包含MCPO_API_KEY。请参阅.env.example.```dotenv
.env file example
pip source used during Docker build (optional, uses default source if empty)
PIP_SOURCE=https://mirrors.aliyun.com/pypi/simple/
API Key required for mcpo runtime (required)
MCPO_API_KEY=your_mcpo_api_key_here
Other API Keys that may be needed for mcp servers (according to config.json)
AMAP_MAPS_API_KEY=your_amap_key
... other required environment variables
- **`config.json`**:配置MCP服务器以启动。参见 `config.example.json`.
- **网络**:确保访问Debian(阿里云镜像)、NodeSource、PyPI(或指定 `PIP_SOURCE`).
### 2.目录结构和关键文件
- `Dockerfile`:定义图像构建过程。
- 基础图像: `python:3.13-slim`
- 安装: `bash`, `curl`, `jq`, `nodejs` (v22.x), `git`, `uv` (通过pip)
- 用户:创建并运行为 `appuser`.
- 配置:支持 `PIP_SOURCE` 构建论点。
- `start.sh`:容器入口点脚本。
- 集合 `HOME`, `UV_CACHE_DIR`, `NPM_CONFIG_CACHE`.
- 创建持久性目录。
- 倒像 `config.json` 并动态安装MCP工具(使用 `uvx` 或 `npx`).
- 开始 `mcpo` 主要服务。
- `docker-compose.yml`:定义服务、构建参数、卷装载、环境变量。
- 通行证 `PIP_SOURCE` 到Dockerfile。
- 支架 `./config.json`, `./logs`, `./data`, `./node_modules`, `./.npm`, `./.uv_cache`.
- 负载 `.env` 作为运行时环境变量,通过 `env_file`.
- `readme-docker.md`:这份文件。
- `test_mcp_tools.sh`:基本功能测试脚本。
### 3.塑造形象```bash
# Pass PIP_SOURCE (compose will automatically read from .env if defined)
docker-compose build [--no-cache]
--no-cache:强制重建所有层以确保最新更改生效。- 构建过程使用
PIP_SOURCE从.env要配置的文件(如果有效)pip来源。
4.启动服务```bash
Start service (run in background)
docker-compose up -d
```
docker-compose.yml从以下位置加载变量.env作为容器运行时环境变量。start.sh执行,动态安装中定义的MCP工具config.json.mcpo主服务启动。
III、 常见问题及解决方法
1. npx: command not found / git: command not found
- 原因:
npx(已安装nodejs)或git未安装或其路径不在appusersPATH环境变量。 - 解决方案:
- 确认
Dockerfilesapt-get install包含nodejs和git. - 确认
ENV PATH指令包括/usr/bin(其中apt-已安装nodejs和git通常居住)。Dockerfile已经包含/app/.local/bin:/usr/bin:/usr/local/bin:$PATH. - 使用
docker-compose build --no-cache重建。
2. mkdir: cannot create directory '/root': Permission denied
- 原因:容器以非root用户身份运行
appuser,但脚本或依赖项试图写入/root目录(例如默认缓存路径)。 - 解决方案:
- 所有缓存目录(
uv,npm)重定向到/app通过ENV指令(UV_CACHE_DIR,NPM_CONFIG_CACHE,HOME). mkdir -p在……里面start.sh仅在以下目录上操作/app.- 中的相应卷装载路径
docker-compose.yml已更新至/app/....
3. pip 不使用自定义源(PIP_SOURCE)
- 原因:
PIP_SOURCE在构建过程中未正确传递到Dockerfile。 - 解决方案:
- 确保
.env文件包含PIP_SOURCE=https://.... - 确保
docker-compose.ymlsbuild.args本节包括- PIP_SOURCE=${PIP_SOURCE:-}. - Dockerfile接收
ARG PIP_SOURCE并使用viaexport PIP_INDEX_URL在……里面RUN层。
4.网络和依赖安装缓慢/失败
- 原因:网络连接不良,访问官方资源缓慢或超时。
- 解决方案:
- Dockerfile配置为使用阿里云镜像加速
apt. pip可以通过以下方式配置家用镜子PIP_SOURCE在……里面.env.- Node.js(NodeSource)和uv(PyPI/Mirror)仍然依赖于网络;在极端情况下考虑其他解决方案。
IV、 关键考虑因素和最佳实践
- 非root用户:始终按以下方式运行容器
appuser. - 持久性:明确安装
config.json,logs,data,node_modules,.npm,.uv_cache以保留状态和依赖关系。 - 秘密:使用管理API密钥和敏感信息
.env文件,通过注入env_file, 从不COPY.env输入图像或硬编码密钥。.env文件应该在.gitignore. - 动态安装:
start.sh的动态安装机制提供了灵活性,但意味着首次启动或之后的启动时间更长config.json变化。 - 版本固定:为了再现性,建议固定
uv版本在Dockerfile(pip install --user uv==X.Y.Z)以及npx包版本在config.json(@amap/amap-maps-mcp-server@X.Y.Z). - 资源限制:在生产环境中,考虑为中的服务设置内存和CPU限制
docker-compose.yml. - 日志:日志输出到已挂载
./logs目录,便于查看和管理。 - 测试:使用
test_mcp_tools.sh用于基本功能验证的脚本。
V.快速参考命令
- 构建图像:
docker-compose build [--no-cache] - 启动服务(后台):
docker-compose up -d
