2026-06-03 15:39:09 +08:00
# =============================================================================
2026-06-05 13:35:14 +08:00
# MinerU on ROCm 7.2.1 Docker Image( HK 云服务器 / 海外版)
2026-06-03 15:39:09 +08:00
# 原生 Linux + Ubuntu 24.04 + ROCm 7.2.1 + PyTorch 2.11.0 + vllm + MinerU 3.2.0
# =============================================================================
FROM ubuntu:24.04
# -- 构建参数 ---------------------------------------------------------------
ARG ARCH = gfx1201
ARG PYTHON_VER = 3 .12
ARG VENV = /opt/mineru_venv
ARG TORCH_INDEX = https://download.pytorch.org/whl/rocm7.2
2026-06-15 10:48:31 +08:00
# -- GitHub 访问(国内无镜像,需代理)----------------------------------------
ARG GIT_PROXY = http://127.0.0.1:8118
2026-06-04 11:27:28 +08:00
2026-06-05 13:35:14 +08:00
# -- 国内镜像 ----------------------------------------------------------------
2026-06-10 10:52:32 +08:00
ARG PIP_INDEX = https://mirrors.aliyun.com/pypi/simple
2026-06-03 16:19:00 +08:00
2026-06-03 15:39:09 +08:00
# -- 环境变量 ---------------------------------------------------------------
ENV DEBIAN_FRONTEND = noninteractive \
PATH = /opt/rocm/bin:/opt/rocm/llvm/bin:${ VENV } /bin:${ PATH } \
PYTORCH_ROCM_ARCH = ${ ARCH } \
FLASH_ATTENTION_TRITON_AMD_ENABLE = TRUE \
MINERU_MODEL_SOURCE = huggingface \
TORCH_ROCM_AOTRITON_ENABLE_EXPERIMENTAL = 1 \
2026-06-03 16:50:52 +08:00
HSA_ENABLE_SDMA = 1 \
2026-06-17 14:58:44 +08:00
VLLM_TARGET_DEVICE = rocm \
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
2026-06-03 15:39:09 +08:00
WORKDIR /opt
# ===========================================================================
2026-06-03 16:19:00 +08:00
# 阶段 1:换国内源 + 安装 ROCm 7.2.1
2026-06-03 15:39:09 +08:00
# ===========================================================================
2026-06-03 16:19:00 +08:00
RUN sed -i 's|http://.*archive.ubuntu.com|http://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list.d/ubuntu.sources && \
sed -i 's|http://.*security.ubuntu.com|http://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list.d/ubuntu.sources && \
2026-06-10 15:43:34 +08:00
export http_proxy = ${ GIT_PROXY } https_proxy = ${ GIT_PROXY } && \
2026-06-03 16:19:00 +08:00
apt-get update && apt-get install -y --no-install-recommends \
2026-06-03 15:39:09 +08:00
wget curl ca-certificates gnupg software-properties-common && \
wget -q https://repo.radeon.com/rocm/rocm.gpg.key -O - | \
gpg --dearmor | tee /etc/apt/trusted.gpg.d/rocm.gpg > /dev/null && \
echo 'deb [arch=amd64] https://repo.radeon.com/rocm/apt/7.2.1 noble main' \
> /etc/apt/sources.list.d/rocm.list && \
2026-06-03 17:18:00 +08:00
printf 'Package: *\nPin: release o=repo.radeon.com\nPin-Priority: 600\n' \
> /etc/apt/preferences.d/rocm-pin-600 && \
2026-06-03 15:39:09 +08:00
apt-get update && \
apt-get install -y --no-install-recommends \
2026-06-03 17:18:00 +08:00
rocminfo rocm-device-libs hip-dev miopen-hip && \
2026-06-03 15:39:09 +08:00
apt-get clean && rm -rf /var/lib/apt/lists/*
# ===========================================================================
2026-06-05 13:35:14 +08:00
# 阶段 2: ROCm 头文件补丁
2026-06-03 15:39:09 +08:00
# ===========================================================================
RUN set -ex && \
2026-06-05 13:35:14 +08:00
# 补丁 1: hipcc/clang 符号链接
2026-06-03 15:39:09 +08:00
ln -sf /usr/bin/hipvars.pm /usr/share/perl5/hipvars.pm && \
2026-06-04 15:57:17 +08:00
([ -f /usr/bin/hipcc.pl ] && ln -sf /usr/bin/hipcc.pl /opt/rocm/bin/hipcc) || echo "hipcc.pl not found, keeping apt-installed hipcc" && \
2026-06-03 15:39:09 +08:00
ln -sf /opt/rocm/llvm/bin/clang-22 /opt/rocm/llvm/bin/clang-17 && \
ln -sf /opt/rocm/llvm/bin/clang++ /opt/rocm/llvm/bin/clang++-17 && \
# 补丁 2: __hip_internal::conditional → std::conditional
find /opt/rocm/include/hip -name "*.h" \
-exec sed -i 's/__hip_internal::conditional/std::conditional/g' {} + && \
2026-06-05 13:35:14 +08:00
# 补丁 3: warpSize 常量
2026-06-03 15:39:09 +08:00
find /opt/rocm/include/hip -name "amd_warp_functions.h" \
-exec sed -i 's/static constexpr int warpSize = __AMDGCN_WAVEFRONT_SIZE;/constexpr int warpSize = 32;/g' {} + && \
# 补丁 4: __activemask() → __builtin_amdgcn_read_exec()
sed -i 's/__activemask()/__builtin_amdgcn_read_exec()/g' \
/opt/rocm/include/hip/amd_detail/amd_warp_sync_functions.h && \
echo "ROCm 7.2.1 header patches applied."
# ===========================================================================
# 阶段 3:系统依赖 + Python 3.12
# ===========================================================================
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential git ninja-build pkg-config \
python${ PYTHON_VER } python${ PYTHON_VER } -venv python${ PYTHON_VER } -dev \
libnuma-dev libdrm2 libhwloc-dev libgl1 \
libgomp1 libopenblas0 && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# ===========================================================================
2026-06-10 15:43:34 +08:00
# 阶段 4:CMake 4.0(通过代理下载加速)
2026-06-03 15:39:09 +08:00
# ===========================================================================
2026-06-15 10:48:31 +08:00
RUN export http_proxy = ${ GIT_PROXY } https_proxy = ${ GIT_PROXY } && \
2026-06-10 15:43:34 +08:00
cd /tmp && \
2026-06-15 10:48:31 +08:00
wget -q https://github.com/Kitware/CMake/releases/download/v4.0.0/cmake-4.0.0-linux-x86_64.tar.gz && \
tar -xzf cmake-4.0.0-linux-x86_64.tar.gz && \
cp -r cmake-4.0.0-linux-x86_64/bin/* /usr/local/bin/ && \
cp -r cmake-4.0.0-linux-x86_64/share/* /usr/local/share/ && \
rm -rf cmake-4.0.0-linux-x86_64* && \
2026-06-03 15:39:09 +08:00
cmake --version
# ===========================================================================
# 阶段 5: Python 虚拟环境 + PyTorch ROCm
# ===========================================================================
RUN python${ PYTHON_VER } -m venv ${ VENV } && \
2026-06-03 16:33:45 +08:00
mkdir -p /root/.pip && \
2026-06-10 17:21:18 +08:00
touch ${ VENV } /torch-constraint.txt && \
2026-06-03 16:33:45 +08:00
echo "[global]" > /root/.pip/pip.conf && \
echo "index-url = ${ PIP_INDEX } " >> /root/.pip/pip.conf && \
2026-06-10 17:18:52 +08:00
echo "[install]" >> /root/.pip/pip.conf && \
echo "constraint = ${ VENV } /torch-constraint.txt" >> /root/.pip/pip.conf && \
2026-06-10 10:52:32 +08:00
${ VENV } /bin/pip install -U pip setuptools wheel && \
2026-06-05 14:18:13 +08:00
# PyTorch ROCm wheels 在海外 CDN,通过代理下载
export http_proxy = ${ GIT_PROXY } https_proxy = ${ GIT_PROXY } && \
2026-06-10 10:52:32 +08:00
${ VENV } /bin/pip install --pre \
2026-06-03 15:39:09 +08:00
torch == 2.11.0+rocm7.2 \
torchvision \
pytorch-triton-rocm \
--index-url ${ TORCH_INDEX } && \
2026-06-10 17:18:52 +08:00
# 锁定 torch 版本,防止后续 pip install 解析到 CUDA 版
echo "torch==2.11.0+rocm7.2" > ${ VENV } /torch-constraint.txt && \
2026-06-05 13:35:14 +08:00
${ VENV } /bin/python -c "import torch; print('PyTorch:', torch.__version__); assert torch.version.hip is not None"
2026-06-03 15:39:09 +08:00
# ===========================================================================
2026-06-05 13:35:14 +08:00
# 阶段 6: ROCm 开发包
2026-06-03 15:39:09 +08:00
# ===========================================================================
2026-06-10 15:43:34 +08:00
RUN export http_proxy = ${ GIT_PROXY } https_proxy = ${ GIT_PROXY } && \
apt-get update && apt-get install -y --no-install-recommends \
2026-06-03 15:39:09 +08:00
hipblas-dev hiprand-dev hipsparse-dev hipsparselt-dev \
hipsolver-dev hipcub-dev rocprim-dev rocthrust-dev \
2026-06-07 03:33:29 +08:00
rocblas-dev rocrand-dev hipfft-dev hipblaslt-dev \
2026-06-07 14:37:15 +08:00
rocsolver-dev rocfft-dev rocsparse-dev rocm-cmake rocm-core && \
2026-06-03 15:39:09 +08:00
apt-get clean && rm -rf /var/lib/apt/lists/*
2026-06-04 15:57:17 +08:00
# ===========================================================================
2026-06-05 13:35:14 +08:00
# 阶段 6.5:安装 amdsmi
2026-06-04 15:57:17 +08:00
# ===========================================================================
RUN if [ -d /opt/rocm/share/amd_smi ] ; then \
cp -r /opt/rocm/share/amd_smi /opt/amd_smi && \
2026-06-10 10:52:32 +08:00
cd /opt/amd_smi && ${ VENV } /bin/pip install . --no-build-isolation && \
2026-06-04 15:57:17 +08:00
echo "amdsmi installed." ; \
else \
echo "amdsmi source not found, skipping." ; \
fi
2026-06-03 15:39:09 +08:00
# ===========================================================================
2026-06-09 15:36:23 +08:00
# 阶段 7:复制预克隆仓库 + 安装 aiter + flash_attn
2026-06-03 15:39:09 +08:00
# ===========================================================================
2026-06-09 15:36:23 +08:00
COPY aiter/ /opt/aiter/
COPY flash-attention/ /opt/flash-attention/
2026-06-03 15:39:09 +08:00
RUN set -ex && \
2026-06-10 10:52:32 +08:00
${ VENV } /bin/pip install -e /opt/aiter && \
${ VENV } /bin/pip install --no-build-isolation -e /opt/flash-attention && \
2026-06-03 15:39:09 +08:00
${ VENV } /bin/python -c "import torch; v=torch.__version__; assert 'rocm' in v, f'PyTorch overwritten: {v}'; print('PyTorch OK:', v)"
# ===========================================================================
2026-06-05 13:35:14 +08:00
# 阶段 8a:编译 vllm( cmake + ninja,最耗时,单独缓存)
2026-06-03 15:39:09 +08:00
# ===========================================================================
2026-06-09 15:36:23 +08:00
COPY vllm/ /opt/vllm/
2026-06-03 15:39:09 +08:00
RUN set -ex && \
2026-06-10 10:52:32 +08:00
${ VENV } /bin/pip install -U \
2026-06-11 15:01:52 +08:00
"setuptools>=77.0.3,<82" setuptools_scm setuptools_rust wheel && \
2026-06-03 15:39:09 +08:00
cd /opt/vllm && \
2026-06-04 15:03:25 +08:00
if [ -f csrc/mamba/mamba_ssm/selective_scan.h ] ; then \
sed -i '109,121s/^/\/\/ /' csrc/mamba/mamba_ssm/selective_scan.h && \
echo "vllm mamba operator+ patch applied." ; \
else \
echo "vllm mamba selective_scan.h not found (upstream removed), skipping patch." ; \
fi && \
2026-06-03 16:49:38 +08:00
mkdir -p /opt/rocm/lib/cmake/hiprand && \
printf 'include(/opt/rocm/lib/cmake/rocrand/rocrand-config.cmake)\nif(TARGET roc::rocrand AND NOT TARGET hip::hiprand)\n add_library(hip::hiprand ALIAS roc::rocrand)\nendif()\n' \
> /opt/rocm/lib/cmake/hiprand/hiprand-config.cmake && \
mkdir -p /opt/rocm/lib/cmake/hipblas && \
2026-06-09 10:20:37 +08:00
printf 'include(/opt/rocm/lib/cmake/rocblas/rocblas-config.cmake)\nif(TARGET roc::rocblas AND NOT TARGET hip::hipblas)\n add_library(hip::hipblas ALIAS roc::rocblas)\nendif()\nif(TARGET roc::rocblas AND NOT TARGET roc::hipblas)\n add_library(roc::hipblas ALIAS roc::rocblas)\nendif()\n' \
2026-06-03 16:49:38 +08:00
> /opt/rocm/lib/cmake/hipblas/hipblas-config.cmake && \
2026-06-07 14:37:15 +08:00
# 批量创建 hip→roc 别名 cmake config(仅原生 config 缺失时创建)
2026-06-07 03:45:18 +08:00
for pair in "hipcub:rocprim" "hipsolver:rocsolver" "hipsparse:rocsparse" "hipfft:rocfft" ; do \
hip_pkg = " ${ pair %%:* } " ; roc_pkg = " ${ pair #*: } " ; \
cfg_dir = "/opt/rocm/lib/cmake/ ${ hip_pkg } " ; \
2026-06-07 14:37:15 +08:00
if [ ! -f " ${ cfg_dir } / ${ hip_pkg } -config.cmake" ] ; then \
mkdir -p " ${ cfg_dir } " && \
printf 'include(/opt/rocm/lib/cmake/%s/%s-config.cmake)\nif(TARGET roc::%s AND NOT TARGET hip::%s)\n add_library(hip::%s ALIAS roc::%s)\nendif()\n' \
" ${ roc_pkg } " " ${ roc_pkg } " " ${ roc_pkg } " " ${ hip_pkg } " " ${ hip_pkg } " " ${ roc_pkg } " \
> " ${ cfg_dir } / ${ hip_pkg } -config.cmake" && \
echo " ${ hip_pkg } -config.cmake created (alias to ${ roc_pkg } )." ; \
else \
echo " ${ hip_pkg } -config.cmake already exists, skipping." ; \
fi ; \
2026-06-07 03:45:18 +08:00
done && \
2026-06-07 03:57:13 +08:00
# 无 roc 对应物的 hip 包,创建 minimal cmake config(强制覆盖)
2026-06-07 03:45:18 +08:00
for pkg in hipblaslt hiprtc; do \
cfg_dir = "/opt/rocm/lib/cmake/ ${ pkg } " ; \
2026-06-07 03:57:13 +08:00
mkdir -p " ${ cfg_dir } " && \
2026-06-09 10:36:21 +08:00
printf 'set(%s_FOUND TRUE)\nset(%s_VERSION "7.2.1")\nif(NOT TARGET hip::%s)\n add_library(hip::%s INTERFACE IMPORTED)\n set_target_properties(hip::%s PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "/opt/rocm/include")\nendif()\nif(NOT TARGET %s::%s)\n add_library(%s::%s ALIAS hip::%s)\nendif()\n' \
2026-06-08 15:34:44 +08:00
" ${ pkg } " " ${ pkg } " " ${ pkg } " " ${ pkg } " " ${ pkg } " \
2026-06-07 03:57:13 +08:00
" ${ pkg } " " ${ pkg } " " ${ pkg } " " ${ pkg } " " ${ pkg } " \
> " ${ cfg_dir } / ${ pkg } -config.cmake" && \
2026-06-09 10:36:21 +08:00
echo " ${ pkg } -config.cmake created (hip:: + ${ pkg } :: aliases)." ; \
2026-06-09 10:29:11 +08:00
done && \
2026-06-09 10:36:21 +08:00
# roc::* 别名(PyTorch Caffe2Targets 直接引用 roc:: 命名空间的 hip 包名)
for pair in \
"hipblas:rocblas" "hiprand:rocrand" "hipsolver:rocsolver" \
2026-06-09 10:42:25 +08:00
"hipsparse:rocsparse" "hipfft:rocfft" "hipcub:rocprim" ; \
2026-06-09 10:36:21 +08:00
do \
2026-06-09 10:29:11 +08:00
hip_pkg = " ${ pair %%:* } " ; roc_pkg = " ${ pair #*: } " ; \
cfg_dir = "/opt/rocm/lib/cmake/ ${ hip_pkg } " ; \
if [ -f " ${ cfg_dir } / ${ hip_pkg } -config.cmake" ] ; then \
2026-06-09 10:36:21 +08:00
if ! grep -q "roc:: ${ hip_pkg } " " ${ cfg_dir } / ${ hip_pkg } -config.cmake" 2>/dev/null; then \
2026-06-09 10:42:25 +08:00
printf 'if(TARGET roc::%s AND NOT TARGET roc::%s)\n add_library(roc::%s ALIAS roc::%s)\nendif()\n' \
" ${ roc_pkg } " " ${ hip_pkg } " " ${ hip_pkg } " " ${ roc_pkg } " \
2026-06-09 10:29:11 +08:00
>> " ${ cfg_dir } / ${ hip_pkg } -config.cmake" && \
2026-06-09 10:42:25 +08:00
echo "roc:: ${ hip_pkg } → roc:: ${ roc_pkg } ." ; \
fi ; \
fi ; \
done && \
# hipblaslt / hiprtc:底层是 INTERFACE IMPORTED(非 ALIAS),roc:: 直接指 hip::
for pkg in hipblaslt hiprtc; do \
cfg_dir = "/opt/rocm/lib/cmake/ ${ pkg } " ; \
if [ -f " ${ cfg_dir } / ${ pkg } -config.cmake" ] ; then \
if ! grep -q "roc:: ${ pkg } " " ${ cfg_dir } / ${ pkg } -config.cmake" 2>/dev/null; then \
printf 'if(TARGET hip::%s AND NOT TARGET roc::%s)\n add_library(roc::%s ALIAS hip::%s)\nendif()\n' \
" ${ pkg } " " ${ pkg } " " ${ pkg } " " ${ pkg } " \
>> " ${ cfg_dir } / ${ pkg } -config.cmake" && \
echo "roc:: ${ pkg } → hip:: ${ pkg } ." ; \
2026-06-09 10:29:11 +08:00
fi ; \
fi ; \
2026-06-07 03:45:18 +08:00
done && \
2026-06-07 03:57:13 +08:00
# miopen minimal config(强制覆盖,miopen-hip 可能不带 cmake config)
mkdir -p /opt/rocm/lib/cmake/miopen && \
2026-06-09 16:18:17 +08:00
# 诊断: MIOpen 库实际位置
echo "=== MIOpen diagnostic ===" && \
find /opt -name "libMIOpen*" -o -name "libmiopen*" 2>/dev/null | head -10 && \
# 创建符号链接,确保链接器能找到
for so in $( find /opt -name "libMIOpen.so*" -o -name "libmiopen.so*" 2>/dev/null | head -1) ; do \
ln -sf " $so " /opt/rocm/lib/libMIOpen.so && \
echo "libMIOpen.so → $so " ; \
done && \
ls -la /opt/rocm/lib/libMIOpen* 2>/dev/null || echo "WARNING: libMIOpen.so not found!" && \
2026-06-09 10:50:26 +08:00
printf 'set(miopen_FOUND TRUE)\nset(miopen_VERSION "3.4.0")\nif(NOT TARGET miopen)\n add_library(miopen SHARED IMPORTED)\n set_target_properties(miopen PROPERTIES IMPORTED_LOCATION "/opt/rocm/lib/libMIOpen.so" INTERFACE_INCLUDE_DIRECTORIES "/opt/rocm/include")\nendif()\n' \
2026-06-07 03:57:13 +08:00
> /opt/rocm/lib/cmake/miopen/miopen-config.cmake && \
2026-06-09 10:50:26 +08:00
echo "miopen-config.cmake created (SHARED IMPORTED)." && \
# 兜底:确保 libMIOpen.so 链接可见
ls /opt/rocm/lib/libMIOpen* /opt/rocm-7.2.1/lib/libMIOpen* 2>/dev/null | head -3 && \
if [ ! -f /opt/rocm/lib/libMIOpen.so ] && [ -f /opt/rocm-7.2.1/lib/libMIOpen.so ] ; then \
ln -sf /opt/rocm-7.2.1/lib/libMIOpen.so /opt/rocm/lib/libMIOpen.so && \
echo "libMIOpen.so symlinked." ; \
fi && \
2026-06-07 03:57:13 +08:00
# amd_comgr minimal config(强制覆盖)
mkdir -p /opt/rocm/lib/cmake/amd_comgr && \
printf 'set(amd_comgr_FOUND TRUE)\nset(amd_comgr_VERSION "2.8.0")\nif(NOT TARGET amd_comgr)\n add_library(amd_comgr INTERFACE IMPORTED)\n set_target_properties(amd_comgr PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "/opt/rocm/include")\nendif()\n' \
> /opt/rocm/lib/cmake/amd_comgr/amd_comgr-config.cmake && \
echo "amd_comgr-config.cmake created (minimal)." && \
2026-06-05 16:15:17 +08:00
# 创建 HIP cmake config( apt 安装的 hip-dev 缺少 find_package 需要的配置)
mkdir -p /opt/rocm/lib/cmake/hip && \
2026-06-08 10:37:37 +08:00
printf 'set(HIP_FOUND TRUE)\nset(HIP_VERSION "7.2.1")\nset(HIP_PLATFORM amd)\nset(HIP_COMPILER /opt/rocm/llvm/bin/clang++)\nset(HIP_RUNTIME rocm)\nset(HIP_INCLUDE_DIRS /opt/rocm/include)\nset(HIP_LIBRARIES /opt/rocm/lib/libamdhip64.so)\nif(NOT TARGET hip::host)\n add_library(hip::host INTERFACE IMPORTED)\n set_target_properties(hip::host PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${HIP_INCLUDE_DIRS}")\nendif()\nif(NOT TARGET hip::device)\n add_library(hip::device INTERFACE IMPORTED)\n set_target_properties(hip::device PROPERTIES INTERFACE_COMPILE_OPTIONS "--offload-arch=${ARCH}")\nendif()\nif(NOT TARGET hip::amdhip64)\n add_library(hip::amdhip64 SHARED IMPORTED)\n set_target_properties(hip::amdhip64 PROPERTIES IMPORTED_LOCATION "/opt/rocm/lib/libamdhip64.so" INTERFACE_INCLUDE_DIRECTORIES "/opt/rocm/include")\nendif()\n' \
2026-06-05 16:15:17 +08:00
> /opt/rocm/lib/cmake/hip/hip-config.cmake && \
2026-06-07 03:21:06 +08:00
# 补丁: ROCm 7.2.1 中 hip_version.h 已移除, 创建兼容头文件供 PyTorch LoadHIP.cmake 使用
if [ ! -f /opt/rocm/include/hip/hip_version.h ] ; then \
mkdir -p /opt/rocm/include/hip && \
printf '#pragma once\n#define HIP_VERSION_MAJOR 7\n#define HIP_VERSION_MINOR 2\n#define HIP_VERSION_PATCH 53211\n#define HIP_VERSION_GITDATE 0\n#define HIP_VERSION (HIP_VERSION_MAJOR * 10000000 + HIP_VERSION_MINOR * 100000 + HIP_VERSION_PATCH)\n' \
> /opt/rocm/include/hip/hip_version.h && \
echo "hip_version.h created." ; \
fi && \
2026-06-03 15:39:09 +08:00
mkdir -p /opt/vllm_build && \
2026-06-05 16:15:17 +08:00
export HIP_PLATFORM = amd HIP_PATH = /opt/rocm ROCM_PATH = /opt/rocm && \
2026-06-09 15:53:08 +08:00
export http_proxy = ${ GIT_PROXY } https_proxy = ${ GIT_PROXY } && \
2026-06-09 16:02:34 +08:00
export LIBRARY_PATH = /opt/rocm/lib:$LIBRARY_PATH && \
2026-06-03 15:39:09 +08:00
cmake -S /opt/vllm -B /opt/vllm_build -G Ninja \
-DCMAKE_BUILD_TYPE= RelWithDebInfo \
-DVLLM_TARGET_DEVICE= rocm \
-DVLLM_PYTHON_EXECUTABLE= ${ VENV } /bin/python \
-DHIP_ROOT_DIR= /opt/rocm \
-DROCM_PATH= /opt/rocm \
-DCMAKE_HIP_ARCHITECTURES= ${ ARCH } \
2026-06-04 15:37:38 +08:00
-DCMAKE_HIP_COMPILER= /opt/rocm/llvm/bin/clang++ \
2026-06-05 09:38:13 +08:00
-DHIP_COMPILER= /opt/rocm/llvm/bin/clang++ \
-DHIP_PATH= /opt/rocm \
2026-06-07 03:27:19 +08:00
-DHIP_INCLUDE_DIR= /opt/rocm/include \
2026-06-09 14:09:28 +08:00
-DCMAKE_PREFIX_PATH= "/opt/rocm; ${ VENV } /lib/python ${ PYTHON_VER } /site-packages/torch/share/cmake" \
2026-06-09 16:11:57 +08:00
-DCMAKE_SHARED_LINKER_FLAGS= "-L/opt/rocm/lib" \
-DCMAKE_EXE_LINKER_FLAGS= "-L/opt/rocm/lib" && \
2026-06-03 15:46:56 +08:00
cd /opt/vllm_build && ninja -j8 && \
2026-06-03 15:39:09 +08:00
cp /opt/vllm_build/*.abi3.so /opt/vllm/vllm/ && \
2026-06-04 13:52:04 +08:00
echo "vllm C++ build complete (layer cached)."
2026-06-08 14:03:06 +08:00
# ===========================================================================
2026-06-10 15:14:00 +08:00
# 阶段 7.5:复制入口 + 辅助脚本
2026-06-08 14:03:06 +08:00
# ===========================================================================
2026-06-10 15:14:00 +08:00
COPY scripts/entrypoint.sh /opt/entrypoint.sh
RUN chmod +x /opt/entrypoint.sh
COPY scripts/cache_warmer.py /opt/scripts/cache_warmer.py
2026-06-08 14:03:06 +08:00
2026-06-04 13:52:04 +08:00
# ===========================================================================
2026-06-05 13:35:14 +08:00
# 阶段 8b:安装 vllm + 平台补丁 + 验证
2026-06-04 13:52:04 +08:00
# ===========================================================================
RUN set -ex && \
2026-06-10 17:54:52 +08:00
export http_proxy = ${ GIT_PROXY } https_proxy = ${ GIT_PROXY } && \
2026-06-17 16:33:02 +08:00
# 1) 安装构建工具(后续 pip install 需要)
2026-06-17 14:16:40 +08:00
${ VENV } /bin/pip install -U "setuptools>=77.0.3" setuptools_scm setuptools_rust wheel && \
2026-06-17 16:33:02 +08:00
# 2) 手动注册 vllm 为 editable package(阶段 8a 已编译 C++ 扩展,此处不触发 cmake)
2026-06-16 17:56:05 +08:00
cd /opt/vllm && \
2026-06-17 16:33:02 +08:00
mkdir -p vllm.egg-info && \
2026-06-18 10:31:22 +08:00
printf 'Metadata-Version: 2.1\nName: vllm\nVersion: 0.11.0\nSummary: A high-throughput and memory-efficient inference and serving engine for LLMs\n' > vllm.egg-info/PKG-INFO && \
2026-06-17 16:33:02 +08:00
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 && \
2026-06-18 10:31:22 +08:00
# 2b) 写 vllm/_version.py(替代 setuptools_scm 生成),避免 vllm.__version__='dev' 触发
# mineru.backend.vlm.utils:88 中 packaging.version.parse 抛 InvalidVersion
printf '__version__ = "0.11.0"\n__version_tuple__ = (0, 11, 0)\n' > /opt/vllm/vllm/_version.py && \
2026-06-17 16:33:02 +08:00
echo "vllm egg-info created (cmake build skipped, C++ extensions from stage 8a)" && \
# 3) 安装 ROCm PyTorch(后续依赖解析用 ROCm 源补齐 triton-rocm)
2026-06-17 13:48:01 +08:00
( ${ VENV } /bin/pip uninstall -y triton triton-rocm 2>/dev/null || true ) && \
2026-06-10 10:52:32 +08:00
${ VENV } /bin/pip install --force-reinstall \
2026-06-03 15:39:09 +08:00
torch == 2.11.0+rocm7.2 torchvision pytorch-triton-rocm \
--index-url ${ TORCH_INDEX } && \
2026-06-17 10:52:45 +08:00
${ VENV } /bin/python -c "import torch; v=torch.__version__; assert 'rocm' in v, f'PyTorch overwritten: {v}'; print('PyTorch OK:', v)" && \
2026-06-17 16:33:02 +08:00
# 4) 安装 vllm 运行时依赖;额外加入 ROCm PyTorch 源,避免传递依赖解析 triton-rocm 失败
2026-06-17 14:13:37 +08:00
grep -vE '^(torch|torchvision|torchaudio|triton|triton-rocm|pytorch-triton|setuptools)' requirements/common.txt > /tmp/vllm_deps.txt && \
${ VENV } /bin/pip install -r /tmp/vllm_deps.txt --extra-index-url ${ TORCH_INDEX } && \
2026-06-17 16:33:02 +08:00
# 5) 再次确认 PyTorch 仍是 ROCm 版
2026-06-17 14:13:37 +08:00
${ VENV } /bin/python -c "import torch; v=torch.__version__; assert 'rocm' in v, f'PyTorch overwritten after vllm deps: {v}'; print('PyTorch still OK:', v)" && \
2026-06-17 16:33:02 +08:00
# 6) 深度验证 vllm(确保 AsyncEngineArgs、AsyncLLM 等关键模块可导入,缺包直接构建失败)
2026-06-16 17:56:05 +08:00
${ VENV } /bin/python -c "from vllm.engine.arg_utils import AsyncEngineArgs; from vllm.v1.engine.async_llm import AsyncLLM; print('vllm deep import OK:', __import__('vllm').__version__)" && \
2026-06-17 16:33:02 +08:00
# 7) 确保 mineru-api 子进程不依赖 PYTHONPATH 也能导入 vllm
2026-06-16 11:46:53 +08:00
echo "/opt/vllm" > ${ VENV } /lib/python${ PYTHON_VER } /site-packages/vllm.pth && \
2026-06-17 16:33:02 +08:00
# 8) 锁定 ROCm 关键包版本(不含 setuptools,避免与 vllm/mineru 依赖冲突)
2026-06-16 17:56:05 +08:00
${ VENV } /bin/pip freeze | grep -iE "^(torch|vllm|triton|pytorch.triton|torchvision|flash.attn|aiter)" >> ${ VENV } /torch-constraint.txt && \
2026-06-03 15:39:09 +08:00
rm -rf /opt/vllm_build
2026-06-03 15:52:29 +08:00
# ===========================================================================
2026-06-11 17:05:40 +08:00
# 阶段 9:安装 MinerU( constraint 保护 ROCm 环境,正常安装其他依赖)
2026-06-03 15:39:09 +08:00
# ===========================================================================
RUN set -ex && \
2026-06-10 17:54:52 +08:00
export http_proxy = ${ GIT_PROXY } https_proxy = ${ GIT_PROXY } && \
2026-06-16 10:49:04 +08:00
${ VENV } /bin/pip install 'mineru[core]' click gradio httpx cbor2 && \
2026-06-16 17:56:05 +08:00
${ VENV } /bin/python -c "import torch; from vllm.engine.arg_utils import AsyncEngineArgs; import mineru; import click; import gradio; import httpx; import cbor2; print('MinerU + Gradio + vllm deep + httpx + cbor2 imports OK')" && \
2026-06-12 10:13:44 +08:00
${ VENV } /bin/mineru-gradio --help >/dev/null
2026-06-03 15:39:09 +08:00
# ===========================================================================
2026-06-03 15:52:29 +08:00
# 阶段 10:入口与最终验证
2026-06-03 15:39:09 +08:00
# ===========================================================================
RUN echo 'source /opt/mineru_venv/bin/activate' >> /etc/bash.bashrc && \
2026-06-16 17:56:05 +08:00
${ VENV } /bin/python -c "import torch; from vllm.engine.arg_utils import AsyncEngineArgs; import mineru; import gradio; import mineru.cli.gradio_app; print('MinerU ROCm Docker Image Ready'); print(f'PyTorch {torch.__version__} OK')"
2026-06-03 15:39:09 +08:00
2026-06-10 15:14:00 +08:00
ENTRYPOINT [ "/opt/entrypoint.sh" ]
2026-06-03 15:39:09 +08:00
CMD [ "bash" ]