项目构建、部署与 Docker 安全执行
项目构建、部署与 Docker 安全执行
学习目标
- 理解 ChatDev 的依赖管理(uv + pyproject.toml)与构建流程
- 掌握 Docker 部署配置与安全执行机制
- 了解 Makefile 目标与开发工作流
- 理解热重载的安全设计(白名单 + 黑名单)
项目实践
依赖管理
ChatDev 使用 uv 作为 Python 包管理器,pyproject.toml 定义项目配置:
[project]name = "DevAll"version = "0.1.0"requires-python = ">=3.12,<3.13"
dependencies = [ "pyyaml", "openai", "tenacity", "mcp", "fastmcp", "faiss-cpu", "fastapi==0.124.0", "uvicorn", "watchfiles", "websockets", "wsproto", "pydantic==2.12.5", "google-genai>=1.52.0", "mem0ai>=1.0.9", # ... 更多依赖]
[build-system]requires = ["hatchling"]build-backend = "hatchling.build"
[tool.uv]package = false # 不打包为发行版关键设计决策:
requires-python = ">=3.12,<3.13":锁定 Python 3.12,避免版本兼容性风险package = false:不打包为可安装库,仅作为应用运行fastapi==0.124.0:版本锁定,避免 API 破坏性变更
Makefile 目标
dev: # 同时启动前后端(开发模式)sync: # 将 yaml_instance/ 同步到数据库validate-yamls: # 校验所有 YAML 工作流文件help: # 显示可用命令列表make dev 的实现:
dev: # 后端:uv run python server_main.py --port 8000 --reload # 前端:cd frontend && VITE_API_BASE_URL=http://localhost:8000 npm run devDocker 部署
Dockerfile
FROM python:3.12-slim
# 安装系统依赖RUN apt-get update && apt-get install -y nodejs npm
# 安装 Python 依赖COPY requirements.txt .RUN pip install -r requirements.txt
# 复制项目文件COPY . /appWORKDIR /app
# 安装前端依赖RUN cd frontend && npm install
# 暴露端口EXPOSE 8000 5173
# 启动命令CMD ["python", "server_main.py", "--port", "8000"]compose.yml
services: chatdev: build: . ports: - "8000:8000" - "5173:5173" env_file: - .env.docker volumes: - ./WareHouse:/app/WareHouse # 持久化输出目录热重载安全设计
ChatDev 的 --reload 机制经过两层防护:
第一层:白名单(监听目录限制)
RELOAD_SOURCE_DIRS = [ "check", "entity", "functions", "mcp_example", "runtime", "schema_registry", "server", "tools", "utils", "workflow",]仅当这些目录中的文件变化时触发重载。Agent 生成的文件(在 WareHouse/ 中)不触发。
第二层:黑名单(排除目录)
_RELOAD_EXCLUDE_DIRS = ("WareHouse", "logs", "data", "temp", "node_modules")_RELOAD_EXCLUDE_MAX_DEPTH = 10
RELOAD_EXCLUDES = [ f"{d}{'/*' * (depth + 1)}" for d in _RELOAD_EXCLUDE_DIRS for depth in range(_RELOAD_EXCLUDE_MAX_DEPTH)]# 产出: WareHouse/*, WareHouse/*/*, ..., 10 层深度为什么需要两层防护?
- 白名单确保只监听源码
- 黑名单作为第二道防线,即使文件在白名单外但被意外匹配也不会触发
watchfiles 依赖
if args.reload and not _watchfiles_available(): logger.warning( "--reload is active but 'watchfiles' is not installed; uvicorn will " "fall back to StatReload, which ignores --reload-exclude patterns." )- watchfiles 已安装:支持排除模式(黑名单生效)
- watchfiles 未安装:降级为 StatReload(忽略黑名单,仅靠白名单防护)
输出目录管理
WareHouse/ # Agent 执行结果输出logs/ # 日志文件data/ # 数据库文件(如 SQLite)temp/ # 临时文件(自动清理)这些目录通过 .gitignore 排除,不纳入版本控制。
问题与规避
| 问题 | 表现 | 规避策略 |
|---|---|---|
| Python 版本不兼容 | <3.13 限制无法在 3.13 上运行 | 使用 uv 管理 Python 版本 |
| Docker 构建慢 | apt-get 和 pip install 耗时长 | 使用多阶段构建 + 缓存层 |
| 热重载误触发 | 即使有白名单仍被触发 | 确保 watchfiles 已安装 |
| WareHouse 目录挂载 | Docker 中目录不存在 | 使用 volumes 自动创建 |
| 端口冲突 | 8000 已被占用 | --port 参数指定其他端口 |
设计取舍
uv vs pip + requirements.txt
| 维度 | uv | pip |
|---|---|---|
| 安装速度 | 极快(Rust 实现) | 慢 |
| 锁文件 | uv.lock(确定性) | requirements.txt(需 freeze) |
| Python 管理 | 内置 | 需 pyenv 等 |
| ChatDev 的选择 | ✅ 使用 | ❌ 仅保留 requirements.txt 兼容 |
ChatDev 保留 requirements.txt 是为了 Docker 兼容(pip 是 Dockerfile 中的默认安装方式)。
Docker vs 本地开发
| 维度 | Docker | 本地开发 |
|---|---|---|
| 环境一致性 | 高(隔离) | 低(依赖本地环境) |
| 启动速度 | 慢(需构建镜像) | 快 |
| 调试 | 困难(需 attach) | 容易 |
| ChatDev 的选择 | 部署用 | 开发用 |