Files
PlantAI-rag-new/docs/bioflow_image_build_playbook.md

200 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 生信分析环境 → Docker 镜像构建方法(Playbook)
> 本文档是把一个 conda 分析环境做成干净 Docker 镜像的标准方法。本次工程先做 8 个镜像(生信流程编排在用的环境),**工程结束后其余 18 个环境全部按本方法补做**(用户 2026-09-05 指示)。执行 agent 必须在构建过程中回填实测数据,使本文档成为可复用的操作手册。
## 1. 目标与原则(用户拍板,不可偏离)
1. **镜像干净**:镜像内只有 root 用户;不存在 `/home/xzq` 或任何宿主机痕迹。
2. **一个镜像 = 一个 conda 环境**:环境内容与宿主 `/home/xzq/miniconda3/envs/<env>` 对应环境**字节级一致**(版本漂移为零)。
3. **环境即镜像的 Python**:环境解包到镜像标准位置 `/opt/conda`,`ENV PATH=/opt/conda/bin:$PATH`,`python`/`Rscript`/各生信工具由 PATH 直达,不写任何绝对路径。
4. **最终镜像无 conda 本体**:conda 只作为打包工具出现在构建期,运行时镜像里没有 conda 可执行文件。
5. **代码零硬编码**:复制进 rag-new 的代码中宿主机绝对路径全部适配(PATH 裸命令/sys.executable),新写代码一律环境变量/配置。
## 2. 适用范围
- **本次(8 个)**:test4py311(16G)→bioflow-gf / gfpy312(5.4G)→bioflow-gfpy / rnaseq(6.1G)→bioflow-rnaseq / rnaR(2.7G)→bioflow-rnaR / ASAW(5.1G)→bioflow-wgs / interproscanpy311(750M)→bioflow-interproscan / panfamily(1.8G)→bioflow-pan / r_de_analysis(1.6G)→bioflow-rde
- **后续(2026-09-06 已完成 16 个,见 §8 台账)**:ani / at_sc / beagle54 / bioinfo / minerupy312 / rice_download / rice_rna / snpeff / testpy311 / vcflinshi / plantai-bff / pymol-env / biolabx-assembly / biolabx-bioinfo-missing / biolabx-smoke-tools / biolabx-variant-tools → 镜像 plantai-env-*:20260906。
**豁免 3 个(不建镜像,理由记入 §8)**:AI_env(12K 空壳仅 conda-meta/etc 目录)、r_de(11M 残壳,r_de_analysis 的旧残留)、miniconda3 base(78G conda 本体,违反「镜像无 conda」红线)
## 3. 前置检查
- [ ] 宿主机 conda-pack 可用(`conda-pack --version`;不可用则 `conda install -c conda-forge conda-pack`)
- [ ] docker 可用且当前用户有构建权限(`docker info`)
- [ ] 磁盘空间 ≥ 环境体积 × 4(tar + 镜像层 + 构建缓存)
- [ ] glibc 对照:`ldd --version`(宿主)vs 基础镜像 glibc——**基础镜像 glibc 必须 ≥ 宿主 glibc**,否则 conda 二进制无法运行
- [ ] 非标准环境先分类:pymol-env 是 venv 非 conda(打包方式见 §7 坑 5);biolabx-* 在 mamba/micromamba 目录(conda-pack 同样适用,注意源路径)
## 4. 标准流程(每环境)
1. **打包**:`conda-pack -n <env> -o /tmp/<env>.tar.gz`(包内符号链接保留;记录打包时长与 tar 体积)
2. **选基底**:干净基础镜像(如 ubuntu:22.04,按 glibc 对照选版本);基底仅提供 glibc 等系统库,不装任何 conda
3. **Dockerfile 多阶段**(参数化模板见 §5):
- 阶段 1:解包 `<env>.tar.gz` 到 `/opt/conda` → `conda-unpack` 重定位前缀 → `ENV PATH=/opt/conda/bin:$PATH`
- 阶段 2(仅内核镜像需要):COPY 内核源码 → 用镜像内解释器 `/opt/conda/bin/python` 跑 build.sh 编译 .so
- 最终阶段:只留 /opt/conda + .so + 明文入口 + 模板/R 脚本等资源;**不含 conda、不含源码**(明文入口除外)
4. **验证**(§6 清单全过才可发布)
5. **tag**:`bioflow-<name>:<版本或日期>`
6. **发布**:本地 `docker build`;跨机 `docker save -o bioflow-<name>.tar <image>` / `docker load`
## 5. Dockerfile 参数化模板
```dockerfile
ARG BASE_IMAGE=ubuntu:22.04
FROM ${BASE_IMAGE} AS unpack
ARG ENV_TAR
ADD ${ENV_TAR} /tmp/env.tar.gz
RUN mkdir -p /opt/conda && \
tar -xzf /tmp/env.tar.gz -C /opt/conda && \
/opt/conda/bin/conda-unpack && \
rm /tmp/env.tar.gz
ENV PATH=/opt/conda/bin:$PATH
ENV LANG=C.UTF-8
# —— 仅内核镜像需要:编译 .so(用镜像内解释器,.so 与解释器版本绑定)——
# COPY --from=src /app/bioflow_kernel /app/bioflow_kernel
# RUN cd /app/bioflow_kernel && /opt/conda/bin/python build.sh <白名单>
FROM ${BASE_IMAGE}
COPY --from=unpack /opt/conda /opt/conda
ENV PATH=/opt/conda/bin:$PATH
ENV LANG=C.UTF-8
# COPY --from=build /app/bioflow_kernel(仅 .so + 明文入口 + 资源)
USER root
```
## 6. 验证清单(每镜像必过)
- [ ] 容器内 `bin/python --version` 与源环境完全一致(版本号+路径前缀重定位后仍可运行)
- [ ] `ldd /opt/conda/bin/python` 无「not found」缺库(conda-unpack 前必须检查,见 §7 坑 3)
- [ ] 代表性工具 `--help`/`--version` 正常(每环境 3-5 个:如 python/Rscript/blastp/mafft/…)
- [ ] 镜像内无 `/home/xzq` 目录、无 `conda` 可执行文件(干净性断言)
- [ ] 内核镜像:`python -c "import gfa_core.xxx"` 加载 .so 成功
- [ ] 金标/冒烟(有金标的环境):如 bioflow-gf 的 identify 24 ID 集合 diff 全等
## 7. 常见坑
1. **符号链接**:conda 环境内部有大量绝对符号链接(→ /home/xzq/miniconda3/pkgs/...),**必须用 conda-pack**(它把链接目标打包为相对链接),直接 `cp -r` 或 `tar` 会坏。
2. **前缀硬编码**:环境内部分文件(bin 脚本 shebang、pyc、pkg-config .pc)写死源前缀 `/home/xzq/miniconda3/envs/<env>`——**必须 `conda-unpack` 重定位**,不跑这步的镜像必坏。
3. **glibc 不匹配**:conda 环境按宿主 glibc 构建,基础镜像 glibc 旧于宿主时二进制缺符号。对照表见 §3。
4. **Cython .so 与解释器绑定**:内核 .so 必须用镜像内解释器在镜像内编译(3.11 的 .so 在 3.8 解释器下加载必炸);编译是构建期动作,最终镜像不含源码。
5. **venv 类环境**(pymol-env):非 conda,`pip freeze` + `python -m venv` 在镜像内重建,或 venv 目录整体拷贝+`sed` 修 shebang;优先 conda-pack 若其支持(实测记录)。
6. **R 环境**:conda-pack 对 R 环境同样有效,但 R 包内嵌路径(.libPaths、Renviron)需在验证阶段实跑 Rscript 加载核心包确认。
7. **体积**:conda-pack 压缩后约为源环境的 35-96%(本次实测: test4py311 44%/interproscan 46%/
rnaseq 38%/rnaR 39%/ASAW 40%/panfamily 35%/gfpy312 53%/r_de_analysis 96%);最终镜像层可再瘦身(删除 __pycache__/conda-meta 可选)。
8. **外部软链(2026-09-06 实测新增)**:dev 环境存在指向宿主其他位置的符号链接(conda-pack 原样打包成镜像内断链):
- interproscanpy311: bin/interproscan → dev tools/ 外部目录(311M); lib/jvm → /usr/lib/jvm
- rnaseq: bin/STAR* ×14 → ~/.local/share/mamba/envs/biolabx-bioinfo-missing/bin
- test4py311: bin/pdftex → ~/.local/TinyTeX(全树无引用, 可删除)
处置: 宿主侧把目标目录打成 extras tar(不动 dev 仓库),Dockerfile `ARG EXTRAS_TAR` 解包到 /opt/ 后
把断链重指镜像内位置;构建前先 `find env -type l` 排查 out-of-prefix 链接。
9. **pkgs 缓存缺失(2026-09-06 实测新增)**:宿主 miniconda3/pkgs 被清理过时 conda-pack 报
`FileNotFoundError: pkgs/xxx/info/files`。修复: 从 `envs/<env>/conda-meta/*.json` 的 paths_data 重建
info/files(脚本见报告附录),或直接 `conda-pack --ignore-missing-files`。
10. **大 tar 零块(2026-09-06 实测新增)**:>4GB 的 tar.gz 中段出现零块填充,GNU tar 报
"跳转到下一个头"退出码 2 但数据完整。Dockerfile 解包一律
`(tar --ignore-zeros -xzf ... || true) && test -x /opt/conda/bin/python` 断言。
11. **ADD 自动解包(2026-09-06 实测新增)**:`ADD x.tar.gz /path` 会被解包成目录,必须用 COPY。
12. **conda-unpack 的 shebang 是 `env python`**:必须在 ENV PATH 之后单独 RUN,否则 exit 127。
13. **docker tag 全小写**:bioflow-rnaR → bioflow-rnar(stage_image_map.json 用 docker_tag 字段区分逻辑名与仓库名)。
14. **基底拉取**:docker.io/nju/rat/1panel 镜像站 blob 端点不通时用 `docker.m.daocloud.io/library/ubuntu:24.04`。
15. **libgomp(2026-09-06 实测新增)**:blastp/R 依赖 libgomp.so.1,而 conda 环境只带 libgomp.so → .1.0.0
(无 .so.1 链接名)。最终阶段加 `ENV LD_LIBRARY_PATH=/opt/conda/lib`,内核镜像再装 ubuntu libgomp1 包。
16. **BuildKit 上下文外软链**:docker build 对上下文外绝对软链按上下文根解析失败;stage 目录建在
pack-dir 下用硬链接 tar + rsync 内核源码(源码仅 ~22M)。
17. **conda-pack -n 需要 conda 在 PATH**(2026-09-06 实测):nohup/后台脚本里 `conda-pack -n <env>`
报 `CondaPackError: Failed to determine path to environment`——它调 conda 解析 env 路径,
PATH 里没有 conda 时即失败(-p 路径打包不受影响)。修法:脚本开头
`export PATH=/home/xzq/miniconda3/bin:$PATH` 或 `env PATH=... conda-pack`。
18. **pip 覆盖检测阻断打包**(2026-09-06 实测):env 内 pip 装过 conda 不管理的文件时报
`Files managed by conda were found to have been deleted/overwritten`(pymol-env 174 个、
minerupy312 多个)。这些是宿主既有历史,非本次改动——加 `--ignore-missing-files` 打包。
19. **无 python 的工具环境(dest-prefix 路线)**(2026-09-06 实测,ani/beagle54/rice_rna/vcflinshi):
环境无 bin/python(纯 C/Java/R/perl 工具)时 conda-unpack 无法运行(shebang 是 env python,
装系统 python3 也因包内文本重定位逻辑可跑但绕)。正解:`conda-pack -n <env> -d /opt/conda`
打包期直接重定位到目标前缀,产物无 conda-unpack;Dockerfile 只需解包+删 conda 桩。
20. **pip entry point shebang 写死源前缀**(2026-09-06 pymol-env 实测):conda-unpack 不重定位
pip 装的 console_scripts(pymol/pip/wheel 等 6 个 shebang 仍是 /home/xzq/...)。
Dockerfile unpack 段统一 `sed -i '1s|.*|#!/opt/conda/bin/python|'` 修复,
最终层断言 `! grep -rlE '^#!.*home/xzq' /opt/conda/bin` 构建期拦截。
21. **conda-unpack 脚本本体含源前缀**:包内 conda-unpack 是文本脚本含源前缀字符串,
重定位完成后必须删(与 conda 桩同批),否则镜像内仍有 /home/xzq 文本痕迹。
## 8. 环境总台账(26 个,动态回填)
| # | 环境 | 位置 | 体积 | 镜像 | 用途 | 状态 |
|---|---|---|---|---|---|---|
| 1 | test4py311 | miniconda3/envs | 16G | bioflow-gf | GF 链主环境 | 已完成(2026-09-06) |
| 2 | gfpy312 | miniconda3/envs | 5.5G | bioflow-gfpy | mafft/iqtree/meme | 已完成(2026-09-06) |
| 3 | rnaseq | miniconda3/envs | 5.2G | bioflow-rnaseq | RNA-seq 主链 | 已完成(2026-09-06) |
| 4 | rnaR | miniconda3/envs | 2.8G | bioflow-rnaR | R 汇总绘图 | 已完成(2026-09-06) |
| 5 | ASAW | miniconda3/envs | 5.0G | bioflow-wgs | WGS/GWAS/群体 | 已完成(2026-09-06) |
| 6 | interproscanpy311 | miniconda3/envs | 707M | bioflow-interproscan | 结构域注释 | 已完成(2026-09-06) |
| 7 | panfamily | miniconda3/envs | 1.8G | bioflow-pan | 泛基因家族 pangene | 已完成(2026-09-06);**2026-09-14 修复**:补 panfamily 模块(68K,COPY 自 pipeline/panfamily/ 进 site-packages)并删指向宿主路径的 activate.d/panfamily.sh(PYTHONPATH 断链);旧镜像 tag=dev-before-panfamily,新镜像已 load 176 并端到端验证 |
| 8 | r_de_analysis | miniconda3/envs | 611M | bioflow-rde | DE 分析 | 已完成(2026-09-06) |
| 9 | AI_env | miniconda3/envs | 12K | — | 空壳(仅 conda-meta/etc) | **豁免**:空壳无内容,不建 |
| 10 | ani | miniconda3/envs | 95M | plantai-env-ani | ANI 计算(fastANI, 无 python→dest-prefix) | 已完成(2026-09-06) |
| 11 | at_sc | miniconda3/envs | 8.9G | plantai-env-at-sc | 拟南芥单细胞(R 4.6.1) | 已完成(2026-09-06) |
| 12 | beagle54 | miniconda3/envs | 393M | plantai-env-beagle54 | Beagle imputation(无 python→dest-prefix) | 已完成(2026-09-06) |
| 13 | bioinfo | miniconda3/envs | 295M | plantai-env-bioinfo | 通用生信(bwa) | 已完成(2026-09-06) |
| 14 | minerupy312 | miniconda3/envs | 8.1G | plantai-env-minerupy312 | MinerU 文档解析 | 已完成(2026-09-06) |
| 15 | rice_download | miniconda3/envs | 417M | plantai-env-rice-download | 水稻数据下载(SRA) | 已完成(2026-09-06) |
| 16 | rice_rna | miniconda3/envs | 455M | plantai-env-rice-rna | 水稻 RNA(无 python→dest-prefix, 补 gcc) | 已完成(2026-09-06) |
| 17 | snpeff | miniconda3/envs | 5.1G | plantai-env-snpeff | SnpEff 注释 | 已完成(2026-09-06) |
| 18 | testpy311 | miniconda3/envs | 149M | plantai-env-testpy311 | 测试环境 | 已完成(2026-09-06) |
| 19 | vcflinshi | miniconda3/envs | 79M | plantai-env-vcflinshi | VCF 处理(perl, 无 python→dest-prefix) | 已完成(2026-09-06) |
| 20 | plantai-bff | miniconda3/envs | 553M | plantai-env-plantai-bff | BFF 服务(uvicorn) | 已完成(2026-09-06) |
| 21 | pymol-env | dev 仓库 tools/ | 1.3G | plantai-env-pymol-env | PyMOL 可视化(conda 环境无 pyvenv.cfg, conda-pack -p 打包) | 已完成(2026-09-06) |
| 22 | biolabx-assembly | mamba/envs | 225M | plantai-env-biolabx-assembly | 组装工具(megahit) | 已完成(2026-09-06) |
| 23 | biolabx-bioinfo-missing | mamba/envs | 1.3G | plantai-env-biolabx-bioinfo | QA 测试工具(STAR) | 已完成(2026-09-06) |
| 24 | biolabx-smoke-tools | micromamba/envs | 217M | plantai-env-biolabx-smoke-tools | QA 测试工具 | 已完成(2026-09-06) |
| 25 | biolabx-variant-tools | micromamba/envs | 284M | plantai-env-biolabx-variant-tools | QA 测试工具(bcftools) | 已完成(2026-09-06) |
| 26 | miniconda3 (base) | miniconda3 | 78G | — | conda 本体 | **豁免**:含 conda 本体违反镜像红线 |
| 27 | r_de | miniconda3/envs | 11M | — | r_de_analysis 旧残留(conda-meta 4 文件) | **豁免**:残壳非独立环境 |
> 台账中「(待测)」体积与「(待确认)」用途由执行 agent 在构建过程中实测/核实后回填。
## 10. BIOFLOW_DATA 数据根部署陷阱(2026-09-06 P7 终验实测)
- **容器内断链**:数据根 zh/bioflow-data 下的 hmm/ 与 rag_db/pfam_mapping.json 若是
指向宿主其他位置的软链,容器内(挂载进 docker)是断链——identify 报
「本地Pfam映射不存在」+「未能从本地映射或RAG服务获取基因家族Pfam」。
- **处置**:挂载进容器的数据必须真实文件(cp -aL 解链复制),不能软链。
已修复:hmm(3.9G 真实文件)+ rag_db/pfam_mapping.json(377B 真实文件)。
- **验证**:容器内 ls /bioflow-data/hmm 可见 Pfam-A.hmm* 五文件、
/bioflow-data/rag_db/pfam_mapping.json 可读。
## 9. 构建实测记录(执行 agent 回填)
| 环境 | conda-pack 时长 | tar 体积 | 解包+unpack 时长 | 最终镜像体积 | 构建总时长 | 验证结果 |
|---|---|---|---|---|---|---|
| test4py311 | 20m39s | 7.1G(压缩比44%) | ~3min(含 --ignore-zeros) | 16.4GB | ~15min(含 .so 编译) | python 3.11.14/ldd 0 缺库/CLEAN/工具+hmmsearch 通过(金标见报告) |
| interproscanpy311 | 1m56s | 343M(46%) | ~6s | 1.18GB | 27s | python 3.11.15/InterProScan 5.78-109.0/java 11/CLEAN |
| gfpy312 | 10m33s | 2.9G(53%) | ~35s | 5.85GB | ~3min | python 3.12.13/CLEAN(mafft 见报告已知限制) |
| rnaseq | 16m52s | 2.0G(38%) | ~45s | 6.58GB | ~3min | python 3.11.15/STAR 2.7.11b/salmon 1.10.3/CLEAN |
| rnaR | 5m37s | 1.1G(39%) | ~30s | 2.93GB | 2m29s | python 3.14.3/R 4.5.2/CLEAN |
| ASAW | 12m40s | 2.0G(40%) | ~40s | 5.43GB | ~4min | python 3.8.18/gatk 4.3.0.0/bwa-mem2/plink 1.90/CLEAN |
| panfamily | 6m55s | 625M(35%) | ~20s | 1.96GB | ~2min | python 3.11.9/mafft/iqtree/fimo/blastp/orthofinder/CLEAN |
| r_de_analysis | 7m13s | 589M(96%) | ~20s | 1.88GB | 3m25s | python 3.14.6/R 4.4.3+DESeq2/CLEAN |
| ani | 5s | 31M | dest-prefix 免 unpack | 178MB | 23s | fastANI 1.34/CLEAN(无 python 环境) |
| beagle54 | 33s | 271M | dest-prefix 免 unpack | 648MB | 47s | beagle(镜像内 java 自足)/CLEAN(无 python) |
| rice_rna | 3m49s | 549M | dest-prefix 免 unpack | 1.96GB | 1m39s | Rscript/CLEAN(无 python, 补 gcc 系统软链) |
| vcflinshi | 22s | 26M | dest-prefix 免 unpack | 173MB | 22s | perl/CLEAN(无 python) |
| rice_download | 4m30s | 178M | ~10s | 569MB | 1m18s | python 3.10.20/fasterq-dump 3.4.1/CLEAN |
| plantai-bff | 2m14s | 178M | ~10s | 608MB | 1m23s | python 3.11.15/uvicorn 0.52.4/CLEAN |
| bioinfo | 25s | 97M | ~8s | 366MB | 1m6s | python 3.14.5/bwa/CLEAN |
| testpy311 | 31s | 72M | ~8s | 289MB | 1m2s | python 3.11.15/pip/CLEAN |
| snpeff | 9m35s | 1.8G | ~25s | 5.62GB | 4m12s | python 3.14.5/java 11/snpEff/CLEAN |
| at_sc | 15m24s | 4.0G(45%) | ~40s | 9.24GB | ~6min | python 3.11.6/R 4.6.1/CLEAN |
| minerupy312 | 11m58s | 4.3G(53%) | ~40s | 8.58GB | ~5min | python 3.12.13/mineru/CLEAN(--ignore-missing-files) |
| pymol-env | 6m3s | 414M(32%) | ~25s | 1.38GB | 2m36s | python 3.12.13/pymol shebang 修复/CLEAN(--ignore-missing-files) |
| biolabx-assembly | 25s | 80M | ~8s | 298MB | 1m5s | python 3.14.6/megahit/CLEAN |
| biolabx-bioinfo-missing | 1m15s | 410M | ~12s | 1.43GB | 1m41s | python 3.13.14/STAR 2.7.11b/CLEAN |
| biolabx-smoke-tools | 58s | 78M | ~8s | 289MB | 1m4s | python 3.14.6/CLEAN |
| biolabx-variant-tools | 39s | 125M | ~9s | 457MB | 1m10s | python 3.14.6/bcftools 1.23.1/CLEAN |
> 注: 上表 16 行均为 2026-09-06 实测; 无 python 的 4 环境走 --dest-prefix 打包(免 conda-unpack);
> 全部 16 镜像通过 §6 清单 + 加强断言(无 conda-unpack 残留、bin 无源前缀 shebang)。