# Python Dependency Image Builder

> 分析项目实际使用的 Python 第三方包，并在 .docker-deps 中生成仅含依赖的基础镜像 Dockerfile、锁定清单、审计报告及可选的应用运行 Compose 模板。用于准备依赖镜像构建上下文和以只读源码挂载运行项目的静态编排文件；本 skill 不调用 Docker、不启动本机程序、不实际构建或运行镜像。若任务要求把业务源码封装进镜像并完成运行验收，应改用 python-api-docker-packager。

- Skill: `codeboy-bot/python-dependency-image-builder` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add codeboy-bot/python-dependency-image-builder`
- Raw SKILL.md: https://api.skillmd.com/api/skills/codeboy-bot/python-dependency-image-builder/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: Codeboy-bot (https://skillmd.com/u/codeboy-bot)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/codeboy-bot/python-dependency-image-builder

---


# 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 打包链路。

## 识别真实依赖

先检查所有适用证据，并记录来源：

1. 读取 `pyproject.toml`、`uv.lock`、`poetry.lock`、`requirements*.txt`、`Pipfile.lock`、`environment*.yml` 等已有声明。
2. 扫描项目中的 Python 文件。优先运行 `python scripts/analyze_imports.py <project-root> --output <report.json>`；脚本会区分标准库、本地模块、第三方模块和无法映射的导入，并记录出现位置。
3. 搜索字符串形式的动态导入、插件注册、可选后端及框架配置；AST 扫描结果不是完整依赖锁。
4. 将导入名映射到发行包名，例如 `cv2 -> opencv-python`、`PIL -> Pillow`、`yaml -> PyYAML`。优先采用项目锁文件和包元数据，不凭印象静默猜测；无法确认的映射写入审计报告并在构建前解决。
5. 区分运行时、开发、测试和可选依赖。默认镜像只纳入运行时依赖；只有用户要求“全部环境依赖”或指定 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`、API `CMD`、端口或健康检查；
- 不默认添加 `# syntax=docker/dockerfile:...` 前端声明；只有确实使用该前端的专有功能时才添加并说明，因为该声明会触发额外的前端镜像拉取；
- 安装完成后执行 `pip check`，并对可安全导入的顶层模块做构建期 smoke test；
- 清理安装缓存；在 OCI 标签中标明其为 dependency/base image，并记录依赖锁摘要；
- 若作为下游基础镜像，清楚说明下游镜像仍需自行复制源码并设置入口。

## 生成应用运行 Compose 模板

用户要求 Compose、运行编排、源码挂载、端口或健康检查模板时，读取 [references/compose-template.md](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` 冲突。

典型构建命令应将隔离目录作为上下文：

```text
docker build -f .docker-deps/Dockerfile -t <name>:<tag> .docker-deps
```

## 验证

验证成本由低到高：

1. 检查审计报告中没有未解决的第三方导入或本地/VCS 冲突。
2. 枚举隔离构建上下文，确认没有业务源码和敏感文件。
3. 静态检查 Dockerfile 不含源码复制、应用入口、端口、健康检查或项目安装命令。
4. 若生成 Compose，静态检查其 YAML 结构，并确认镜像标签、入口、端口、环境变量、健康检查和所有宿主机挂载均有来源或被明确标为待配置；确认源码挂载为只读、写目录单独挂载且不含明文密钥。
5. 检查构建命令以隔离目录为 context，并提供用户自行执行的 build、`pip check`、导入 smoke test 和可选 Compose 启动命令。
6. 明确说明本次只完成静态验证，镜像与 Compose 尚未实际构建或运行；不得执行这些命令。

依赖镜像和 Compose 模板不需要证明 API 健康、端口可访问或脚本能运行；这些属于运行验收。

## 完成标准

- 项目导入、已有声明、锁文件和选定依赖组之间的差异已解释。
- 发行包名、版本、来源和无法确认项记录在依赖审计报告中。
- 构建上下文只包含构建依赖镜像所需的依赖元数据，不含业务源码或敏感信息。
- Dockerfile 内置 `pip check` 和导入 smoke test，但实际结果留待用户构建时确认。
- 用户要求 Compose 时，`.docker-deps/` 中存在经过静态检查的 Compose 文件；源码只读挂载、可写目录、数据路径、入口、端口和健康检查与项目证据一致，未知项清楚标注。
- 交付说明明确 Python 版本、目标平台、依赖组、建议镜像 tag、构建命令、可选 Compose 命令、尚未实际构建或运行，以及依赖镜像脱离源码挂载后不能直接运行项目。

