Python Dependency Image Builder
生成 Python 依赖基础镜像构建文件,以及可选的应用运行 Compose 模板。最重要的不变量是:依赖镜像构建上下文不得包含项目业务源码、算法脚本、应用入口、模型或业务数据。Compose 可以在运行时把宿主机项目目录只读挂载到容器,但这不会把源码复制或安装进依赖镜像。本 skill 只交付静态文件,绝不调用 Docker CLI/daemon、Docker Compose、启动 Docker Desktop 或其他本机程序,也不实际生成、运行、导出镜像。
边界
本 skill 只负责:
- 从 Python 源文件、依赖清单和锁文件识别项目实际使用的第三方包;
- 固化选定依赖及必要的系统运行库;
- 生成隔离的依赖镜像构建上下文、Dockerfile、锁定依赖和依赖审计报告;
- 按用户要求生成
.docker-deps/docker-compose.yaml(或用户指定文件名),用依赖镜像配合只读源码挂载运行项目; - 对构建上下文、Dockerfile 和 Compose 文件做静态检查;
- 提供由用户自行执行的构建、验证、标记、运行或导出命令。
本 skill 不负责:
COPY、安装或执行项目自身的.py文件、包目录或其他业务源码;- 把未经项目配置或用户输入确认的入口、端口、健康检查、数据挂载和环境配置写成确定值;
- 修改业务代码以适配容器;
- 将项目作为 wheel/sdist 安装,因为这会把项目源码装入镜像。
- 调用
docker build/run/pull/save/inspect、Docker Compose 或任何镜像工具; - 启动 Docker Desktop、Docker daemon、虚拟机或其他本机程序;
- 声称镜像已经构建或运行验证通过。
Compose 只是让依赖镜像通过宿主机源码挂载执行现有项目,不改变“依赖镜像本身不能直接运行项目”的事实。用户要求把源码封装进镜像、修改应用以适配容器、实际启动或做健康验收时,说明需求已经超出本 skill;路由到 python-api-docker-packager。用户只要求依赖基础镜像或静态 Compose 模板时,不要加载或套用 API 打包链路。
识别真实依赖
先检查所有适用证据,并记录来源:
- 读取
pyproject.toml、uv.lock、poetry.lock、requirements*.txt、Pipfile.lock、environment*.yml等已有声明。 - 扫描项目中的 Python 文件。优先运行
python scripts/analyze_imports.py <project-root> --output <report.json>;脚本会区分标准库、本地模块、第三方模块和无法映射的导入,并记录出现位置。 - 搜索字符串形式的动态导入、插件注册、可选后端及框架配置;AST 扫描结果不是完整依赖锁。
- 将导入名映射到发行包名,例如
cv2 -> opencv-python、PIL -> Pillow、yaml -> PyYAML。优先采用项目锁文件和包元数据,不凭印象静默猜测;无法确认的映射写入审计报告并在构建前解决。 - 区分运行时、开发、测试和可选依赖。默认镜像只纳入运行时依赖;只有用户要求“全部环境依赖”或指定 extra/group 时才加入开发、测试或可选组,并在镜像标签和报告中说明。
不要直接把当前虚拟环境的 pip freeze 当作项目依赖;它可能包含未使用包和工具链污染。可以用它补充版本证据,但必须与项目声明和导入使用交叉核对。
固化依赖
- 已有锁文件时优先服从锁文件,并保留其 Python 版本、平台 marker、索引和哈希语义。
- 只有未锁定的声明时,生成独立的、可审查的锁定清单;不要覆盖用户现有依赖文件,除非用户明确要求。
- 若
pyproject.toml工具只能通过“安装当前项目”解析依赖,先导出为 requirements/constraints,再在镜像中安装导出结果;禁止pip install .、uv sync或poetry install将当前项目本身装入依赖镜像。 - 包含本地路径、editable、workspace member、私有 VCS 或项目自身 wheel 的依赖不能直接进入“无业务源码”镜像。先报告冲突,让用户选择发布为独立依赖制品、排除它或扩大任务范围。
- 私有索引凭据只通过 BuildKit secret 或构建环境注入,不写入 Dockerfile、依赖文件、镜像层、构建参数默认值或归档。
- 根据目标平台选择 wheel 和必要系统运行库。编译器、头文件和下载缓存留在 builder 阶段;runtime 阶段只保留 Python 包和必要动态库。
创建隔离构建上下文
在项目内使用专门目录(默认 .docker-deps/,或遵从用户指定位置),只放:
- 依赖镜像专用
Dockerfile; - 导出的锁定 requirements/constraints 或解析依赖必需的清单副本;
- 明确需要的系统包清单、CA 证书或 pip 配置模板;
- 依赖审计报告和不含密钥的构建说明。
- 可选的
docker-compose.yaml;它可以引用宿主机源码和数据的绝对路径,但文件本身不得包含源码或凭据。
先列出上下文内容,再交付。上下文中出现业务 .py、应用包目录、模型、数据、.env、密钥或完整项目清单时停止并修正。Dockerfile 禁止 COPY .、ADD . 及指向项目源码的跨目录复制。命令示例必须以该隔离目录本身作为 Docker build context,从机制上保证父项目文件不可见。
Dockerfile 应满足:
- 基础 Python 主/次版本与项目约束一致;固定明确版本,发布复现性要求高时固定 digest;
- 先复制依赖清单,再安装依赖,保持缓存层稳定;
- 不声明业务
ENTRYPOINT、APICMD、端口或健康检查; - 不默认添加
# syntax=docker/dockerfile:...前端声明;只有确实使用该前端的专有功能时才添加并说明,因为该声明会触发额外的前端镜像拉取; - 安装完成后执行
pip check,并对可安全导入的顶层模块做构建期 smoke test; - 清理安装缓存;在 OCI 标签中标明其为 dependency/base image,并记录依赖锁摘要;
- 若作为下游基础镜像,清楚说明下游镜像仍需自行复制源码并设置入口。
生成应用运行 Compose 模板
用户要求 Compose、运行编排、源码挂载、端口或健康检查模板时,读取 references/compose-template.md,并在 .docker-deps/ 下生成文件。默认文件名为 docker-compose.yaml;用户明确指定 dockers-compose.yaml 或其他名称时服从用户。
Compose 与依赖镜像职责必须分开:
image引用本次建议的依赖镜像标签,不在 Compose 中构建或安装项目;- 将项目源码目录挂载到
/app:ro,设置working_dir: /app,再通过 exec 数组形式的command执行现有入口; output、logs、cache等确需写入的子目录使用单独的可写 bind mount 覆盖只读源码挂载;- 按项目配置中真实使用的数据路径补充挂载。只读数据默认加
:ro,确需写入时才去掉; - 从用户输入和项目配置提取服务名、镜像名、入口、端口、环境变量和健康检查路径。证据不足时使用明显占位符、注释说明或省略可选字段,不静默猜测;
- 不写入密码、令牌或私有索引凭据。敏感值只引用运行时环境变量或单独的、未纳入交付的 env 文件;
- 不添加顶层
version;端口和可能被 YAML 转型的环境变量使用字符串;健康检查优先使用 Python 标准库,避免假设镜像含有curl。
若同一 Compose 需要多个服务,可以复用同一个依赖镜像,但逐一确认服务名、容器名、命令、端口和挂载,避免端口或 container_name 冲突。
典型构建命令应将隔离目录作为上下文:
docker build -f .docker-deps/Dockerfile -t <name>:<tag> .docker-deps
验证
验证成本由低到高:
- 检查审计报告中没有未解决的第三方导入或本地/VCS 冲突。
- 枚举隔离构建上下文,确认没有业务源码和敏感文件。
- 静态检查 Dockerfile 不含源码复制、应用入口、端口、健康检查或项目安装命令。
- 若生成 Compose,静态检查其 YAML 结构,并确认镜像标签、入口、端口、环境变量、健康检查和所有宿主机挂载均有来源或被明确标为待配置;确认源码挂载为只读、写目录单独挂载且不含明文密钥。
- 检查构建命令以隔离目录为 context,并提供用户自行执行的 build、
pip check、导入 smoke test 和可选 Compose 启动命令。 - 明确说明本次只完成静态验证,镜像与 Compose 尚未实际构建或运行;不得执行这些命令。
依赖镜像和 Compose 模板不需要证明 API 健康、端口可访问或脚本能运行;这些属于运行验收。
完成标准
- 项目导入、已有声明、锁文件和选定依赖组之间的差异已解释。
- 发行包名、版本、来源和无法确认项记录在依赖审计报告中。
- 构建上下文只包含构建依赖镜像所需的依赖元数据,不含业务源码或敏感信息。
- Dockerfile 内置
pip check和导入 smoke test,但实际结果留待用户构建时确认。 - 用户要求 Compose 时,
.docker-deps/中存在经过静态检查的 Compose 文件;源码只读挂载、可写目录、数据路径、入口、端口和健康检查与项目证据一致,未知项清楚标注。 - 交付说明明确 Python 版本、目标平台、依赖组、建议镜像 tag、构建命令、可选 Compose 命令、尚未实际构建或运行,以及依赖镜像脱离源码挂载后不能直接运行项目。