Files
mineru-rocm/docker/ISSUES.md
T
2026-06-17 16:33:02 +08:00

385 lines
14 KiB
Markdown
Raw 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 构建问题汇总
> 目标:Ubuntu 24.04 + ROCm 7.2.1 + vllm + MinerU Docker 镜像
> 环境:原生 Linux + RX 9070 (gfx1201) + Privoxy (127.0.0.1:8118)
---
## 1. 网络类
### 1.1 Docker Hub 拉基础镜像超时
**现象**:`dial tcp [2a03:2880:...]:443 i/o timeout`
**原因**:`docker.io` 被墙,IPv6 直连超时
**解决**:Docker daemon 配置代理 + 国内镜像加速器
```bash
# /etc/systemd/system/docker.service.d/http-proxy.conf
Environment="HTTP_PROXY=http://127.0.0.1:8118"
Environment="HTTPS_PROXY=http://127.0.0.1:8118"
# /etc/docker/daemon.json
{
"registry-mirrors": ["https://docker.1panel.live", ...],
"ipv6": false
}
```
### 1.2 容器内无法访问国内镜像
**现象**:`Could not resolve 'mirrors.tuna.tsinghua.edu.cn'`
**原因**:Docker 默认 bridge 网络无法路由到外网
**解决**:`docker-compose.yml` 构建时加 `network: host`(非代理,只是共享宿主机网络栈)
### 1.3 GitHub 直连失败
**现象**:`git clone github.com` → `GnuTLS recv error` / `TLS connection non-properly terminated`
**原因**:GitHub 在国内不通,无可靠国内镜像
**解决**:git/wget 通过 Privoxy 代理访问 GitHub(**仅 GitHub**,其他源用国内镜像)
```dockerfile
ARG GIT_PROXY=http://127.0.0.1:8118
git config --global http.proxy ${GIT_PROXY}
# wget: export http_proxy=${GIT_PROXY}
```
### 1.4 git clone 代理断连
**现象**:`RPC failed; curl 92 HTTP/2 stream 5 was not closed cleanly: CANCEL`
**原因**:HTTP/2 通过代理传大仓库不稳定
**解决**:禁用 HTTP/2 + 加大 buffer
```bash
git config --global http.version HTTP/1.1
git config --global http.postBuffer 524288000
```
### 1.5 PyTorch ROCm wheels 下载中断
**现象**:`IncompleteRead` (pip 下载 .whl 到一半断开)
**原因**:PyTorch 官方 CDN (`download.pytorch.org`) 在国内直连不稳定
**解决**:下载 PyTorch 时设环境变量走代理
```bash
export http_proxy=http://127.0.0.1:8118 https_proxy=http://127.0.0.1:8118
pip install ... --pre torch==2.11.0+rocm7.2 ...
```
### 1.6 flash-attention 子模块代理递归断连
**现象**:`--recursive` 克隆 flash-attention 时子模块 `cutlass` (~200MB) 下载失败:`RPC failed; curl 56 GnuTLS recv error`
**原因**:3 个子模块(composable_kernel + cutlass + aiter)挤在一条代理链路上,大文件容易丢包
**解决**(可选):宿主机预克隆后 COPY 入镜像。或用 `--depth 1` + 逐个 `git submodule update --init --depth 1`(断了一个可单独重试)
---
## 2. Dockerfile 语法类
### 2.1 ENV 行内注释导致解析失败
**现象**:`Syntax error - can't find = in "\ "`,行号为 `HSA_ENABLE_SDMA=1 \ # 注释`
**原因**:Docker ENV 不允许行内 `#` 注释
**解决**:删除行内注释,或移到单独 `#` 行
### 2.2 多行 `python -c "..."` 被误解析
**现象**:`dockerfile parse error: unknown instruction: import` / `unknown instruction: from`
**原因**:Docker 解析器把 Python `-c` 的多行字符串当作 Dockerfile 指令(`from x import y` → 误认为 `FROM`;`import x` → 误认为未知指令)
**解决**:复杂 Python 代码写成独立脚本,用 `COPY` 进入镜像后 `python /opt/xxx.py` 执行
涉及的文件:
- `scripts/apply_mineru_patches.py` — MinerU RDNA 适配补丁
- `scripts/patch_vllm_platform.py` — vllm 平台检测补丁
---
## 3. ROCm 兼容性类
### 3.1 版本号锁定失效
**现象**:`Version '1.0.0.70201-38~24.04' for 'rocminfo' was not found`
**原因**:AMD 仓库更新后精确版本号过期
**解决**:改用 apt pinning 策略,不锁死版本号
```bash
# /etc/apt/preferences.d/rocm-pin-600
Package: *
Pin: release o=repo.radeon.com
Pin-Priority: 600
```
### 3.2 hipcc.pl 符号链接创建损坏链接
**现象**:cmake 报 `Can't find CUDA or HIP installation`(PyTorch 的 `LoadHIP.cmake:179`)
**原因**:`ln -sf /usr/bin/hipcc.pl /opt/rocm/bin/hipcc`,`/usr/bin/hipcc.pl` 在原生 Linux 上不存在,创建了损坏的符号链接
**解决**:条件创建,源文件不存在时跳过
```bash
([ -f /usr/bin/hipcc.pl ] && ln -sf /usr/bin/hipcc.pl /opt/rocm/bin/hipcc) || echo "hipcc.pl not found"
```
### 3.3 缺 rocm-cmake 导致 find_package(HIP) 失败
**现象**:PyTorch `LoadHIP.cmake:179` 调用 `find_package_and_print_version` 找不到 HIP
**原因**:未安装 `rocm-cmake` 包,缺少 HIP cmake 发现模块
**解决**:在阶段 6 加装 `rocm-cmake`
### 3.4 vllm mamba operator+ 补丁失效
**现象**:`sed: can't read csrc/mamba/mamba_ssm/selective_scan.h: No such file or directory`
**原因**:vllm 上游已移除 mamba 模块
**解决**:改为条件判断,文件不存在就跳过
```bash
if [ -f csrc/mamba/mamba_ssm/selective_scan.h ]; then sed ...; else echo "skipping"; fi
```
### 3.5 原生 Linux 需要 amdsmi + 平台检测补丁
**现象**(社区反馈):`ModuleNotFoundError: amdsmi` → `current_platform = UnspecifiedPlatform` → `Device string must not be empty`
**原因**:amdsmi 未安装,且 `logger.warning_once()` 触发 vllm 循环导入
**解决**:
1. 安装 amdsmi(原生 Linux 上可用,WSL2 不需要)
2. 补丁 6:`platforms/__init__.py` 加 `torch.version.hip` 兜底
3. 补丁 7:`platforms/rocm.py` 中 `logger.warning_once()` → `sys.stderr.write()`
### 3.6 缺 hip_version.h 头文件
**现象**:`Could not find hip/hip_version.h or rocm-core/rocm_version.h`
**原因**:ROCm 7.2.1 的 apt 安装已将 `hip_version.h` 从默认路径移除,且 `rocm-core` 包未安装
**解决**:
1. 安装 `rocm-core` 包(提供 `rocm_version.h`)
2. 手动创建 `/opt/rocm/include/hip/hip_version.h` 兼容头文件
```bash
apt-get install -y rocm-core
# 兜底:手动生成 hip_version.h
printf '#define HIP_VERSION_MAJOR 7\n#define HIP_VERSION_MINOR 2\n...'
```
### 3.7 cmake 需显式设 HIP 编译器路径
**现象**:仅设 `PATH` + `HIP_ROOT_DIR` + `ROCM_PATH` 不足以让 cmake 发现 HIP
**解决**:显式指定
```
-DCMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++ # (非 hipcc,CMake 4.0 拒绝)
-DHIP_COMPILER=/opt/rocm/llvm/bin/clang++ # PyTorch LoadHIP 也需要
-DHIP_PATH=/opt/rocm
-DCMAKE_PREFIX_PATH="/opt/rocm;..."
```
### 3.8 PyTorch Caffe2Targets 缺失 cmake target(Docker 容器特有)
**现象**:cmake 反复报 `hip::amdhip64` / `hiprtc::hiprtc` / `roc::hipblas` / `roc::hipblaslt` 等 target 未找到
**原因**:裸机部署时 ROCm 的 cmake 配置通过 `/opt/rocm` 完整安装,cmake 能自动发现所有 target。但 Docker 容器内 apt 安装的 dev 包缺少部分 cmake config 文件,PyTorch 的 `Caffe2Targets.cmake` 硬编码引用了这些 target
**涉及 target 及修复**:
| 报错 target | 命名空间问题 | 最终 alias |
|:--|:--|:--|
| `hip::amdhip64` | 普通 target | SHARED IMPORTED → `libamdhip64.so` |
| `hiprtc::hiprtc` | 需双冒号命名空间 | `hiprtc::hiprtc` ALIAS `hip::hiprtc` |
| `roc::hipblas` | roc:: 而非 hip:: | `roc::hipblas` ALIAS `roc::rocblas` |
| `roc::hipblaslt` | 同上 | `roc::hipblaslt` ALIAS `hip::hipblaslt` |
| `roc::hiprand` / `roc::hipsolver` 等 | 同上 | 各指向对应 `roc::roc*` target |
**注意**:`roc::hip*` → 应直接指向底层 `roc::roc*`(不能通过 `hip::hip*` 中转,因为后者本身是 ALIAS,CMake 不允许链式 ALIAS)
### 3.9 rocm-core-dev → rocm-core 包名错误
**现象**:`E: Unable to locate package rocm-core-dev`
**原因**:ROCm 7.2.1 仓库中的包名为 `rocm-core`(无 -dev 后缀)
**解决**:`s/rocm-core-dev/rocm-core/`
### 3.10 -lMIOpen 链接失败
**现象**:`/usr/bin/ld: cannot find -lMIOpen`
**原因**:miopen cmake config 使用了 `INTERFACE IMPORTED`(无实际 .so 路径),链接器找不到 `libMIOpen.so`
**解决**:改为 `SHARED IMPORTED` + 指定 `IMPORTED_LOCATION`,并检查版本化目录的符号链接
```cmake
# 错误
add_library(miopen INTERFACE IMPORTED)
# 正确
add_library(miopen SHARED IMPORTED)
set_target_properties(miopen PROPERTIES
IMPORTED_LOCATION "/opt/rocm/lib/libMIOpen.so"
INTERFACE_INCLUDE_DIRECTORIES "/opt/rocm/include")
```
### 3.11 printf 参数计数错误
**现象**:cmake 报 `add_library` 在第 11 行语法错误(`hiprtc-config.cmake:11`)
**原因**:生成 cmake config 的 shell printf 格式串含 13 个 `%s`,但只传了 12 个参数,最后一行 `hip::%s` 未替换
**解决**:减少单行 printf 参数,复杂结构拆成独立循环
---
## 4. Docker 缓存策略
### 4.1 vllm 编译+验证同层导致缓存丢失
**现象**:ninja 编译 30 分钟成功后被后面验证失败拖垮,全部重来
**解决**:拆为 8a(编译)和 8b(安装+验证)
| 层 | 内容 | 缓存行为 |
|:--|:--|:--|
| 8a | git clone + cmake + ninja | 编译成功即缓存,**永不丢失** |
| 8b | pip install + PyTorch 修复 + 平台补丁 | 失败可重试,不影响 8a |
### 4.2 缓存失效条件
任一 RUN 层的指令或上下文变化都会导致该层及之后所有层重建。修改 `ARG`、`ENV`、`COPY` 文件内容均会触发。
### 4.3 COPY 脚本在 RUN 引用之后
**现象**:阶段 8b 执行 `python /opt/patch_vllm_platform.py` → 文件不存在
**原因**:`COPY scripts/patch_vllm_platform.py` 在阶段 8.5(原序号),但阶段 8b 已引用该脚本——Dockerfile 中 COPY 位于引用它的 RUN 之后
**解决**:将 COPY 指令移到所有需要脚本的 RUN 之前(阶段 7.5)。规则:**COPY 必须在引用它的 RUN 之前**
---
## 5. 网络策略总览
| 资源 | 访问方式 |
|:--|:--|
| Docker Hub | daemon 代理 + 国内镜像加速器 |
| Ubuntu apt | 清华镜像 `mirrors.tuna.tsinghua.edu.cn` |
| PyPI pip | 清华镜像 `pypi.tuna.tsinghua.edu.cn/simple` |
| AMD ROCm apt | `repo.radeon.com` 直连 |
| PyTorch ROCm wheels | `download.pytorch.org` 直连 |
| GitHub (git/wget) | **Privoxy 代理 127.0.0.1:8118**(唯一例外) |
---
## 6. 构建阶段类
### 6.1 阶段 8b `pip install -e .` 触发 cmake 配置失败
**现象**:阶段 8a(cmake + ninja 手动编译)成功,但阶段 8b 执行 `pip install -e . --no-build-isolation --no-deps` 时报错:
```
TorchConfig.cmake:62 (find_package)
→ CMakeLists.txt:95 (find_package)
→ Configuring incomplete, errors occurred!
error: failed-wheel-build-for-install
× Failed to build installable wheels for some pyproject.toml based projects
╰─> vllm
```
**排查过程**:
Dockerfile 设计为阶段 8a 手动执行 `cmake -S ... -B ... -G Ninja`(携带完整 `-D` 参数)编译 vllm C++ 扩展并复制 `.abi3.so` 文件,阶段 8b 再用 `pip install -e .` 注册 Python 包。但 `pip install -e .` 通过 vllm 的 setuptools 构建扩展**再次触发 cmake**,且 vllm 内部的 cmake 调用与手动 cmake 在以下方面不可控:
1. **尝试一(ENV 透传)**:在 Dockerfile `ENV` 块中添加 `CMAKE_PREFIX_PATH`、`CMAKE_HIP_COMPILER`、`ROCM_PATH` 等 8 个 cmake 环境变量,期望 pip 触发的 cmake 继承这些值。**无效**——vllm 的 `cmake_build_ext` 内部会独立构造 cmake 参数,不完全依赖环境变量。
2. 错误始终出现在 `TorchConfig.cmake:62` 调用 `find_package(Caffe2)` 时,Caffe2 targets 引用的 ROCm cmake 目标无法被 pip 触发的 cmake 解析。
**结论**:`pip install -e .` 触发的 cmake 构建过程与阶段 8a 的手动 cmake 不在同一个可控环境中,且阶段 8b 的 `pip install -e .` 本质上是**冗余的**——C++ 扩展已在阶段 8a 编译完成。
**最终解决**:**跳过 pip install -e .,手动创建 vllm editable package 元数据**。
核心思路:阶段 8a 负责所有 C++ 编译(`.abi3.so`),阶段 8b 只负责 Python 包注册(不触发 cmake)。
具体改动(Dockerfile 阶段 8b):
```bash
# 替换前(会触发 cmake,失败):
cd /opt/vllm && \
${VENV}/bin/pip install -e . --no-build-isolation --no-deps && \
# 替换后(手动创建 egg-info,不触发 cmake):
cd /opt/vllm && \
mkdir -p vllm.egg-info && \
cat > vllm.egg-info/PKG-INFO << 'VLLM_EOF' && \
Metadata-Version: 2.1
Name: vllm
Version: 0.0.0
Summary: A high-throughput and memory-efficient inference and serving engine for LLMs
VLLM_EOF
echo "vllm" > vllm.egg-info/top_level.txt && \
touch vllm.egg-info/dependency_links.txt && \
touch vllm.egg-info/requires.txt && \
find vllm -name "*.py" -type f 2>/dev/null | sort > vllm.egg-info/SOURCES.txt && \
echo "vllm egg-info created (cmake build skipped, C++ extensions from stage 8a)" && \
```
手动创建的 egg-info 包含以下文件:
| 文件 | 内容 | 用途 |
|------|------|------|
| `PKG-INFO` | `Name: vllm` + `Version: 0.0.0` | `pip freeze` / `importlib.metadata` 识别 |
| `top_level.txt` | `vllm` | 声明顶层包名 |
| `SOURCES.txt` | 所有 `.py` 文件列表 | 包文件索引 |
| `dependency_links.txt` | 空文件 | 依赖链接(无) |
| `requires.txt` | 空文件 | 运行依赖(由后续 pip install -r 安装) |
`import vllm` 的路径解析由现有的 `.pth` 文件保证:
```bash
echo "/opt/vllm" > ${VENV}/lib/python${PYTHON_VER}/site-packages/vllm.pth
```
**附:ENV 块新增的 cmake 变量(保留,对阶段 8a 和其他 cmake 调用有益)**:
```dockerfile
ENV ... \
CMAKE_PREFIX_PATH=/opt/rocm \
CMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++ \
HIP_COMPILER=/opt/rocm/llvm/bin/clang++ \
HIP_PATH=/opt/rocm \
HIP_ROOT_DIR=/opt/rocm \
HIP_INCLUDE_DIR=/opt/rocm/include \
HIP_PLATFORM=amd \
ROCM_PATH=/opt/rocm
```
**效果**:
- 阶段 8b 不再触发 cmake,消除了冗余编译(节省约 30 分钟)
- C++ 扩展只在阶段 8a 编译一次,职责清晰
- `pip list` / `pip freeze` 正常显示 vllm
- `import vllm` 在所有 Python 进程中正常工作
---
*最后更新: 2026-06-17*