chore: import upstream snapshot with attribution
This commit is contained in:
+1131
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,323 @@
|
||||
# This vLLM Dockerfile is used to build images that can run vLLM on both x86_64 and arm64 CPU platforms.
|
||||
#
|
||||
# Supported platforms:
|
||||
# - linux/amd64 (x86_64)
|
||||
# - linux/arm64 (aarch64)
|
||||
#
|
||||
# Use the `--platform` option with `docker buildx build` to specify the target architecture, e.g.:
|
||||
# docker buildx build --platform=linux/arm64 -f docker/Dockerfile.cpu .
|
||||
#
|
||||
# Build targets:
|
||||
# vllm-openai (default): used for serving deployment
|
||||
# vllm-openai-zen: vLLM from source + zentorch from PyPI via vllm[zen]
|
||||
# vllm-test: used for CI tests
|
||||
# vllm-dev: used for development
|
||||
#
|
||||
# Build arguments:
|
||||
# PYTHON_VERSION=3.13|3.12 (default)|3.11|3.10
|
||||
# VLLM_CPU_X86=false (default)|true (for cross-compilation)
|
||||
# VLLM_CPU_ARM_BF16=false (default)|true (for cross-compilation)
|
||||
#
|
||||
|
||||
######################### COMMON BASE IMAGE #########################
|
||||
FROM ubuntu:22.04 AS base-common
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
ARG PYTHON_VERSION=3.12
|
||||
|
||||
ARG max_jobs=32
|
||||
ENV MAX_JOBS=${max_jobs}
|
||||
|
||||
# Install minimal dependencies and uv
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||||
apt-get update -y \
|
||||
&& apt-get install -y --no-install-recommends sudo ccache git curl wget ca-certificates zlib1g-dev \
|
||||
gcc-12 g++-12 libtcmalloc-minimal4 libnuma-dev ffmpeg libsm6 libxext6 libgl1 jq lsof make xz-utils \
|
||||
&& update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 10 --slave /usr/bin/g++ g++ /usr/bin/g++-12 \
|
||||
&& curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
# Compiler and linker environment
|
||||
ENV CC=/usr/bin/gcc-12 CXX=/usr/bin/g++-12
|
||||
ENV CCACHE_DIR=/root/.cache/ccache
|
||||
ENV CMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
ENV PATH="/root/.local/bin:$PATH"
|
||||
ENV VIRTUAL_ENV="/opt/venv"
|
||||
ENV UV_PYTHON_INSTALL_DIR=/opt/uv/python
|
||||
RUN uv venv --python ${PYTHON_VERSION} --seed ${VIRTUAL_ENV}
|
||||
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
|
||||
|
||||
ENV UV_HTTP_TIMEOUT=500
|
||||
|
||||
# Install Python dependencies
|
||||
ENV UV_INDEX_STRATEGY="unsafe-best-match"
|
||||
ENV UV_LINK_MODE="copy"
|
||||
|
||||
# Copy requirements files for installation
|
||||
COPY requirements/common.txt requirements/common.txt
|
||||
COPY requirements/cpu.txt requirements/cpu.txt
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install --upgrade pip && \
|
||||
uv pip install -r requirements/cpu.txt --torch-backend cpu
|
||||
|
||||
ARG TARGETARCH
|
||||
ENV TARGETARCH=${TARGETARCH}
|
||||
|
||||
######################### x86_64 BASE IMAGE #########################
|
||||
FROM base-common AS base-amd64
|
||||
|
||||
ENV LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4:/opt/venv/lib/libiomp5.so"
|
||||
|
||||
######################### arm64 BASE IMAGE #########################
|
||||
FROM base-common AS base-arm64
|
||||
|
||||
ENV LD_PRELOAD="/usr/lib/aarch64-linux-gnu/libtcmalloc_minimal.so.4"
|
||||
|
||||
######################### BASE IMAGE #########################
|
||||
FROM base-${TARGETARCH} AS base
|
||||
|
||||
RUN echo 'ulimit -c 0' >> ~/.bashrc
|
||||
|
||||
######################### RUST BUILD IMAGE #########################
|
||||
# Build the Rust frontend (`vllm-rs`) in a dedicated stage so the wheel build
|
||||
# stage doesn't need the rust toolchain or protoc. This stage runs in parallel
|
||||
# with the main vllm-build stage.
|
||||
FROM ubuntu:22.04 AS rust-build
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update -y \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates curl git build-essential unzip python3 python3-pip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY tools/install_protoc.sh /tmp/install_protoc.sh
|
||||
RUN /tmp/install_protoc.sh && rm /tmp/install_protoc.sh
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
COPY requirements/build/rust.txt requirements/build/rust.txt
|
||||
RUN python3 -m pip install --no-cache-dir -r requirements/build/rust.txt
|
||||
|
||||
# Copy only the Rust build inputs; build_rust.sh publishes artifacts needed
|
||||
# by the wheel build stage.
|
||||
COPY rust rust
|
||||
COPY rust-toolchain.toml rust-toolchain.toml
|
||||
COPY tools/build_rust.py tools/build_rust.py
|
||||
COPY build_rust.sh build_rust.sh
|
||||
|
||||
# Cap cargo parallelism to avoid exhausting the CI host's open-file limit
|
||||
# (rustc spawns enough concurrent processes to hit RLIMIT_NOFILE otherwise).
|
||||
ENV CARGO_BUILD_JOBS=4
|
||||
|
||||
# Build the release artifacts. Cache cargo registry/git, but not target/,
|
||||
# because stale target metadata can outlive source updates across BuildKit
|
||||
# cache reuse.
|
||||
RUN --mount=type=cache,target=/root/.cargo/registry,sharing=locked \
|
||||
--mount=type=cache,target=/root/.cargo/git,sharing=locked \
|
||||
bash build_rust.sh
|
||||
|
||||
######################### BUILD IMAGE #########################
|
||||
FROM base AS vllm-build
|
||||
|
||||
ARG GIT_REPO_CHECK=0
|
||||
# Support for cross-compilation with x86 ISA including AVX2 and AVX512: docker build --build-arg VLLM_CPU_X86="true" ...
|
||||
ARG VLLM_CPU_X86=0
|
||||
ENV VLLM_CPU_X86=${VLLM_CPU_X86}
|
||||
# Support for cross-compilation with ARM BF16 ISA: docker build --build-arg VLLM_CPU_ARM_BF16="true" ...
|
||||
ARG VLLM_CPU_ARM_BF16=0
|
||||
ENV VLLM_CPU_ARM_BF16=${VLLM_CPU_ARM_BF16}
|
||||
|
||||
WORKDIR /vllm-workspace
|
||||
|
||||
# Validate build arguments - prevent mixing incompatible ISA flags
|
||||
RUN if [ "$TARGETARCH" = "arm64" ] && [ "$VLLM_CPU_X86" != "0" ]; then \
|
||||
echo "ERROR: Cannot use x86-specific ISA flags (AVX2, AVX512, etc.) when building for ARM64 (--platform=linux/arm64)"; \
|
||||
exit 1; \
|
||||
fi && \
|
||||
if [ "$TARGETARCH" = "amd64" ] && [ "$VLLM_CPU_ARM_BF16" != "0" ]; then \
|
||||
echo "ERROR: Cannot use ARM-specific ISA flags (ARM_BF16) when building for x86_64 (--platform=linux/amd64)"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
# Copy build requirements
|
||||
COPY requirements/build/cpu.txt requirements/build/cpu.txt
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install -r requirements/build/cpu.txt --torch-backend cpu
|
||||
|
||||
COPY . .
|
||||
|
||||
# Drop the pre-built Rust artifacts into the source tree. setup.py detects
|
||||
# them and ships them as-is, skipping the local Rust build.
|
||||
COPY --from=rust-build /workspace/vllm/vllm-rs vllm/vllm-rs
|
||||
COPY --from=rust-build /workspace/vllm/_rust_*.so vllm/
|
||||
|
||||
RUN if [ "$GIT_REPO_CHECK" != 0 ]; then bash tools/check_repo.sh ; fi
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=cache,target=/root/.cache/ccache \
|
||||
--mount=type=cache,target=/vllm-workspace/.deps,sharing=locked \
|
||||
VLLM_TARGET_DEVICE=cpu python3 setup.py bdist_wheel --dist-dir=dist --py-limited-api=cp38
|
||||
|
||||
######################### TRITON-CPU BUILD IMAGE #########################
|
||||
FROM base AS vllm-triton-cpu-build
|
||||
|
||||
# Support for cross-compilation with x86 ISA including AVX2 and AVX512: docker build --build-arg VLLM_CPU_X86="true" ...
|
||||
# Re-declared here because this stage is `FROM base` (not `vllm-build`), so it
|
||||
# does not inherit the ARG/ENV defined there. Without it, the guard below would
|
||||
# see an empty value and build triton-cpu on non-x86 targets (e.g. arm64).
|
||||
ARG VLLM_CPU_X86=0
|
||||
|
||||
WORKDIR /vllm-workspace
|
||||
|
||||
RUN mkdir dist
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=cache,target=/root/.cache/ccache \
|
||||
--mount=type=cache,target=/vllm-workspace/.deps,sharing=locked \
|
||||
if [ "$TARGETARCH" = "amd64" ] || [ "$VLLM_CPU_X86" != "0" ]; then \
|
||||
git clone --recurse-submodules "https://github.com/triton-lang/triton-cpu.git"; \
|
||||
cd triton-cpu; \
|
||||
git checkout "270e696d"; \
|
||||
uv build --wheel --out-dir=../dist; \
|
||||
fi
|
||||
|
||||
######################### TEST DEPS #########################
|
||||
FROM base AS vllm-test-deps
|
||||
|
||||
WORKDIR /vllm-workspace
|
||||
|
||||
# Test requirements are compiled from requirements/test/cuda.in into
|
||||
# requirements/test/cpu.txt by the pip-compile-cpu pre-commit hook, which
|
||||
# resolves CPU wheels via uv's --torch-backend cpu.
|
||||
COPY requirements/test/cpu.txt requirements/test/cpu.txt
|
||||
|
||||
# cpu.txt is compiled for x86_64, so platform markers are resolved away. Drop
|
||||
# packages unavailable on aarch64 (decord, terratorch) for arm builds.
|
||||
RUN case "$(uname -m)" in \
|
||||
aarch64|arm64) sed -i '/^decord==/d; /^terratorch==/d' requirements/test/cpu.txt ;; \
|
||||
esac
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install -r requirements/test/cpu.txt --torch-backend cpu
|
||||
|
||||
######################### DEV IMAGE #########################
|
||||
FROM vllm-build AS vllm-dev
|
||||
|
||||
WORKDIR /vllm-workspace
|
||||
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||||
apt-get install -y --no-install-recommends vim numactl clangd-14
|
||||
|
||||
RUN ln -s /usr/bin/clangd-14 /usr/bin/clangd
|
||||
|
||||
# install development dependencies (for testing)
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install --no-build-isolation -e tests/vllm_test_utils
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=cache,target=/root/.cache/ccache \
|
||||
--mount=type=bind,source=.git,target=.git \
|
||||
VLLM_TARGET_DEVICE=cpu python3 setup.py develop
|
||||
|
||||
COPY --from=vllm-test-deps /vllm-workspace/requirements/test/cpu.txt requirements/test/cpu.txt
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install -r requirements/lint.txt && \
|
||||
uv pip install -r requirements/test/cpu.txt --torch-backend cpu && \
|
||||
pre-commit install --hook-type pre-commit --hook-type commit-msg
|
||||
|
||||
ENTRYPOINT ["bash"]
|
||||
|
||||
######################### TEST IMAGE #########################
|
||||
FROM vllm-test-deps AS vllm-test
|
||||
|
||||
WORKDIR /vllm-workspace
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=bind,from=vllm-build,src=/vllm-workspace/dist,target=dist \
|
||||
uv pip install dist/*.whl
|
||||
|
||||
ADD ./tests/ ./tests/
|
||||
ADD ./examples/ ./examples/
|
||||
ADD ./benchmarks/ ./benchmarks/
|
||||
ADD ./vllm/collect_env.py .
|
||||
ADD ./docker/ ./docker/
|
||||
ADD ./.buildkite/ ./.buildkite/
|
||||
|
||||
# install development dependencies (for testing)
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install -e tests/vllm_test_utils
|
||||
|
||||
# enable fast downloads from hf (for testing)
|
||||
ENV HF_XET_HIGH_PERFORMANCE 1
|
||||
|
||||
# increase timeout for hf downloads (for testing)
|
||||
ENV HF_HUB_DOWNLOAD_TIMEOUT 60
|
||||
|
||||
######################### RELEASE IMAGE #########################
|
||||
FROM base AS vllm-openai
|
||||
|
||||
# Re-declared here because this stage is `FROM base` (not `vllm-build`), so the
|
||||
# RUN below that gates the triton-cpu wheel install on $VLLM_CPU_X86 would
|
||||
# otherwise see an empty value and try to install it on non-x86 targets.
|
||||
ARG VLLM_CPU_X86=0
|
||||
|
||||
WORKDIR /vllm-workspace
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=cache,target=/root/.cache/ccache \
|
||||
--mount=type=bind,from=vllm-build,src=/vllm-workspace/dist,target=dist \
|
||||
uv pip install "$(realpath dist/*.whl)[audio]"
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=cache,target=/root/.cache/ccache \
|
||||
--mount=type=bind,from=vllm-triton-cpu-build,src=/vllm-workspace/dist,target=dist \
|
||||
if [ "$TARGETARCH" = "amd64" ] || [ "$VLLM_CPU_X86" != "0" ]; then \
|
||||
uv pip install "$(realpath dist/*.whl)"; \
|
||||
fi
|
||||
|
||||
# Add labels to document build configuration
|
||||
LABEL org.opencontainers.image.title="vLLM CPU"
|
||||
LABEL org.opencontainers.image.description="vLLM inference engine for CPU platforms"
|
||||
LABEL org.opencontainers.image.vendor="vLLM Project"
|
||||
LABEL org.opencontainers.image.source="https://github.com/vllm-project/vllm"
|
||||
|
||||
# Build configuration labels
|
||||
ARG TARGETARCH
|
||||
ARG VLLM_CPU_X86
|
||||
ARG VLLM_CPU_ARM_BF16
|
||||
ARG PYTHON_VERSION
|
||||
|
||||
LABEL ai.vllm.build.target-arch="${TARGETARCH}"
|
||||
LABEL ai.vllm.build.cpu-x86="${VLLM_CPU_X86:-false}"
|
||||
LABEL ai.vllm.build.cpu-arm-bf16="${VLLM_CPU_ARM_BF16:-false}"
|
||||
LABEL ai.vllm.build.python-version="${PYTHON_VERSION:-3.12}"
|
||||
|
||||
# Copy the examples directory (including the chat/tool templates) so it is
|
||||
# present in the released image, as the CUDA image ships it too. The vllm-test
|
||||
# stage above adds examples/ for testing only, so without this the published
|
||||
# vllm-openai-cpu image would not ship examples/*.jinja.
|
||||
COPY examples examples
|
||||
|
||||
ENTRYPOINT ["vllm", "serve"]
|
||||
|
||||
|
||||
######################### ZEN CPU PYPI IMAGE #########################
|
||||
FROM vllm-openai AS vllm-openai-zen
|
||||
|
||||
ARG TARGETARCH
|
||||
|
||||
RUN if [ "$TARGETARCH" != "amd64" ]; then \
|
||||
echo "ERROR: vllm-openai-amd only supports --platform=linux/amd64"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install "vllm[zen]"
|
||||
|
||||
ENTRYPOINT ["vllm", "serve"]
|
||||
@@ -0,0 +1,156 @@
|
||||
# Base UBI image
|
||||
ARG BASE_UBI_IMAGE_TAG=9.6-1754584681
|
||||
|
||||
###############################################################
|
||||
# BUILDER STAGE #
|
||||
###############################################################
|
||||
|
||||
FROM registry.access.redhat.com/ubi9/ubi-minimal:${BASE_UBI_IMAGE_TAG} AS builder-base
|
||||
|
||||
ARG VLLM_VERSION="0.22.1"
|
||||
ARG PYTHON_VERSION=3.12
|
||||
ARG VLLM_TARGET_DEVICE=cpu
|
||||
|
||||
USER root
|
||||
WORKDIR /root
|
||||
|
||||
ENV HOME=/root \
|
||||
WHEEL_DIR=/wheelsdir \
|
||||
VIRTUAL_ENV=/opt/vllm \
|
||||
GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1 \
|
||||
CARGO_HOME=/root/.cargo \
|
||||
RUSTUP_HOME=/root/.rustup \
|
||||
UV_CACHE_DIR=$HOME/.cache/uv \
|
||||
PATH=/root/.cargo/bin:/root/.rustup/bin:${VIRTUAL_ENV}/bin:$PATH
|
||||
|
||||
RUN echo "DEBUG: VLLM_VERSION=${VLLM_VERSION}"
|
||||
RUN --mount=type=cache,target=/var/cache/dnf \
|
||||
microdnf install -y \
|
||||
python${PYTHON_VERSION}-devel python${PYTHON_VERSION}-pip \
|
||||
&& python${PYTHON_VERSION} -m venv ${VIRTUAL_ENV} \
|
||||
&& python${PYTHON_VERSION} -m pip install -U pip uv --no-cache
|
||||
|
||||
# Important: Copy only bare minimum required for the script to run
|
||||
COPY requirements/ requirements/
|
||||
COPY pyproject.toml ./
|
||||
|
||||
# The script is expected to install whatever python dependencies are missing
|
||||
# as well as whatever system libraries need to be installed from source
|
||||
COPY build_vllm_*.sh ./
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
sh ./build_vllm_$(uname -m).sh
|
||||
|
||||
# copy vllm source code to build cache
|
||||
COPY . .
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
source /opt/rh/gcc-toolset-14/enable && \
|
||||
pip install -U uv
|
||||
|
||||
# build & install vLLM so that all transitive dependencies are build/downloaded into the uv cache
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
source /opt/rh/gcc-toolset-14/enable && \
|
||||
export PATH=/opt/rh/gcc-toolset-14/root/usr/bin:$PATH && \
|
||||
export CC=/opt/rh/gcc-toolset-14/root/usr/bin/gcc && \
|
||||
export CXX=/opt/rh/gcc-toolset-14/root/usr/bin/g++ && \
|
||||
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/lib64/pkgconfig:$PKG_CONFIG_PATH && \
|
||||
export CMAKE_PREFIX_PATH=/usr/local:/usr:$CMAKE_PREFIX_PATH && \
|
||||
export Protobuf_PROTOC_EXECUTABLE=/usr/bin/protoc && \
|
||||
export CFLAGS="-mcpu=power10 -mtune=power10" && \
|
||||
export CXXFLAGS="-mcpu=power10 -mtune=power10" && \
|
||||
export DNNL_ARCH_OPT_FLAGS="-mcpu=power10 -mtune=power10" && \
|
||||
export C_INCLUDE_PATH=/usr/local/include:$C_INCLUDE_PATH && \
|
||||
export CPLUS_INCLUDE_PATH=/usr/local/include:$CPLUS_INCLUDE_PATH && \
|
||||
uv pip install 'setuptools>=78.1.1' && \
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/OpenBLAS/lib/:/usr/local/lib64:/usr/local/lib && \
|
||||
export LIBGOMP=/opt/rh/gcc-toolset-14/root/usr/lib/gcc/ppc64le-redhat-linux/14/libgomp.so && \
|
||||
|
||||
export CMAKE_LIBRARY_PATH=$(dirname $LIBGOMP):${CMAKE_LIBRARY_PATH} && \
|
||||
export LIBRARY_PATH=$(dirname $LIBGOMP):${LIBRARY_PATH} && \
|
||||
export LD_LIBRARY_PATH=$(dirname $LIBGOMP):${LD_LIBRARY_PATH} && \
|
||||
|
||||
echo "LIBGOMP=${LIBGOMP}" && \
|
||||
find /root/.cache/uv -name "*.whl" && \
|
||||
SETUPTOOLS_SCM_PRETEND_VERSION="$VLLM_VERSION" uv build \
|
||||
--wheel --out-dir ${WHEEL_DIR} --no-build-isolation && \
|
||||
uv pip install "$(echo ${WHEEL_DIR}/vllm*.whl)[tensorizer]" --refresh
|
||||
|
||||
###############################################################
|
||||
# FINAL VLLM IMAGE STAGE #
|
||||
###############################################################
|
||||
|
||||
FROM registry.access.redhat.com/ubi9/ubi-minimal:${BASE_UBI_IMAGE_TAG} AS vllm-openai
|
||||
|
||||
ARG PYTHON_VERSION=3.12
|
||||
ENV VLLM_NO_USAGE_STATS=1
|
||||
|
||||
# Set Environment Variables for venv & openblas
|
||||
ENV VIRTUAL_ENV=/opt/vllm
|
||||
ENV PCP_DIR=/opt/rh/gcc-toolset-14/root
|
||||
ENV PATH=${VIRTUAL_ENV}/bin:${PCP_DIR}/usr/bin:/usr/local/bin:$PATH
|
||||
ENV PKG_CONFIG_PATH=${PCP_DIR}/usr/lib64/pkgconfig:/usr/local/lib/pkgconfig/
|
||||
ENV C_INCLUDE_PATH="/usr/local/include:$C_INCLUDE_PATH"
|
||||
ENV LD_LIBRARY_PATH=${PCP_DIR}/usr/lib64:${PCP_DIR}/usr/lib:${VIRTUAL_ENV}/lib64/python${PYTHON_VERSION}/site-packages/torch/lib:/usr/local/lib:$LD_LIBRARY_PATH:/usr/local/lib64:/usr/lib64:/usr/lib
|
||||
ENV UV_LINK_MODE=copy
|
||||
ARG VLLM_VERSION="0.22.1"
|
||||
ARG UV_EXTRA_INDEX_URL="https://wheels.developerfirst.ibm.com/ppc64le/linux/+simple/"
|
||||
ENV UV_EXTRA_INDEX_URL=${UV_EXTRA_INDEX_URL}
|
||||
ENV UV_INDEX_STRATEGY=first-match
|
||||
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
rpm -ivh https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm && \
|
||||
microdnf install --nodocs -y \
|
||||
libomp libicu tar autoconf automake libtool findutils openssl numactl numactl-devel \
|
||||
pkgconfig xsimd gcc-toolset-14 libsndfile \
|
||||
libtiff libjpeg openjpeg2 zlib zeromq \
|
||||
freetype lcms2 libwebp tcl tk utf8proc \
|
||||
harfbuzz fribidi libraqm libimagequant libxcb util-linux gperftools-libs \
|
||||
python${PYTHON_VERSION}-devel python${PYTHON_VERSION}-pip \
|
||||
&& source /opt/rh/gcc-toolset-14/enable \
|
||||
&& microdnf update -y \
|
||||
&& microdnf clean all
|
||||
|
||||
# The `lscpu` command was added as a requirement in part of https://github.com/vllm-project/vllm/pull/21032, so installing it.
|
||||
RUN microdnf install --nodocs -y util-linux && \
|
||||
microdnf clean all
|
||||
|
||||
COPY --from=builder-base /usr/lib64/libprotobuf.so.25 /usr/lib64/
|
||||
COPY --from=builder-base /usr/lib64/libprotobuf.so.25.0.0 /usr/lib64/
|
||||
|
||||
# Use builder venv in final stage instead of wheel reinstallation
|
||||
COPY --from=builder-base /opt/vllm /opt/vllm
|
||||
|
||||
ENV LD_PRELOAD=/usr/lib64/libtcmalloc.so.4
|
||||
|
||||
WORKDIR /home/vllm
|
||||
|
||||
# setup non-root user for OpenShift
|
||||
RUN umask 002 && \
|
||||
useradd --uid 2000 --gid 0 vllm && \
|
||||
mkdir -p /home/vllm && \
|
||||
chmod g+rwx /home/vllm
|
||||
|
||||
ENV HOME=/home/vllm
|
||||
|
||||
# Add labels to document build configuration
|
||||
LABEL org.opencontainers.image.title="vLLM CPU"
|
||||
LABEL org.opencontainers.image.description="vLLM inference engine for CPU platforms"
|
||||
LABEL org.opencontainers.image.vendor="vLLM Project"
|
||||
LABEL org.opencontainers.image.source="https://github.com/vllm-project/vllm"
|
||||
|
||||
# Build configuration labels
|
||||
ARG TARGETARCH
|
||||
ARG VLLM_CPU_PPC64LE
|
||||
ARG PYTHON_VERSION
|
||||
|
||||
LABEL ai.vllm.build.target-arch="${TARGETARCH}"
|
||||
LABEL ai.vllm.build.cpu-ppc64le="${VLLM_CPU_PPC64LE:-false}"
|
||||
LABEL ai.vllm.build.python-version="${PYTHON_VERSION:-3.12}"
|
||||
|
||||
USER 2000
|
||||
|
||||
ENTRYPOINT ["vllm", "serve"]
|
||||
|
||||
|
||||
@@ -0,0 +1,744 @@
|
||||
# default base image
|
||||
ARG REMOTE_VLLM="0"
|
||||
ARG COMMON_WORKDIR=/app
|
||||
ARG BASE_IMAGE=rocm/vllm-dev:base
|
||||
ARG CI_BASE_IMAGE=rocm/vllm-dev:ci_base
|
||||
# NIC backend for MoRI RDMA support.
|
||||
# By default (all), drivers and userspace libraries for all supported NIC types
|
||||
# (ainic and bnxt) are installed; MoRI selects the appropriate one at runtime.
|
||||
# To install drivers for a single NIC type only, set NIC_BACKEND explicitly:
|
||||
# --build-arg NIC_BACKEND=ainic # AMD AINIC (Pensando) only
|
||||
# --build-arg NIC_BACKEND=bnxt # Broadcom Thor-2 only
|
||||
# --build-arg NIC_BACKEND=none # Install nothing.
|
||||
ARG NIC_BACKEND=all
|
||||
# AMD AINIC apt repo settings
|
||||
# Users can specify a custom version compatible with their host drivers.
|
||||
# The default version has been tested with ioinic-dkms=25.11.1.001
|
||||
ARG AINIC_VERSION=1.117.3-hydra
|
||||
ARG UBUNTU_CODENAME=jammy
|
||||
|
||||
# Sccache configuration. Release builds use this today; CI can opt in when a
|
||||
# shared S3-compatible cache backend is available.
|
||||
ARG USE_SCCACHE
|
||||
ARG SCCACHE_DOWNLOAD_URL
|
||||
ARG SCCACHE_ENDPOINT
|
||||
ARG SCCACHE_BUCKET_NAME=vllm-build-sccache
|
||||
ARG SCCACHE_REGION_NAME=us-west-2
|
||||
ARG SCCACHE_S3_NO_CREDENTIALS=0
|
||||
|
||||
FROM ${BASE_IMAGE} AS base
|
||||
|
||||
ARG ARG_PYTORCH_ROCM_ARCH
|
||||
ENV PYTORCH_ROCM_ARCH=${ARG_PYTORCH_ROCM_ARCH:-${PYTORCH_ROCM_ARCH}}
|
||||
|
||||
# Install build dependencies and utilities
|
||||
RUN apt-get update -q -y && apt-get install -q -y \
|
||||
sqlite3 libsqlite3-dev libfmt-dev libmsgpack-dev libsuitesparse-dev \
|
||||
apt-transport-https ca-certificates wget curl \
|
||||
libnuma-dev ccache mold
|
||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||
python3 -m pip install --upgrade pip
|
||||
# Note: mold is installed but not set as the system default linker because
|
||||
# some packages use JIT compilation at runtime with flags mold does not support.
|
||||
# Build stages opt in via LDFLAGS="-fuse-ld=mold".
|
||||
# Remove sccache only if not using sccache (it exists in base image from Dockerfile.rocm_base)
|
||||
ARG USE_SCCACHE
|
||||
RUN if [ "$USE_SCCACHE" != "1" ]; then \
|
||||
apt-get purge -y sccache || true; \
|
||||
python3 -m pip uninstall -y sccache || true; \
|
||||
rm -f "$(which sccache)" || true; \
|
||||
fi
|
||||
|
||||
# Install UV — download first, then run, so a curl failure is not masked by the pipe
|
||||
RUN curl -LsSf --retry 3 --retry-delay 5 https://astral.sh/uv/install.sh -o /tmp/uv-install.sh \
|
||||
&& env UV_INSTALL_DIR="/usr/local/bin" sh /tmp/uv-install.sh \
|
||||
&& rm -f /tmp/uv-install.sh \
|
||||
&& uv --version
|
||||
|
||||
# This timeout (in seconds) is necessary when installing some dependencies via uv since it's likely to time out
|
||||
# Reference: https://github.com/astral-sh/uv/pull/1694
|
||||
ENV UV_HTTP_TIMEOUT=500
|
||||
ENV UV_INDEX_STRATEGY="unsafe-best-match"
|
||||
# Use copy mode to avoid hardlink failures with Docker cache mounts
|
||||
ENV UV_LINK_MODE=copy
|
||||
# ccache directory - persisted across layer rebuilds via cache mounts.
|
||||
ENV CCACHE_DIR=/root/.cache/ccache
|
||||
ENV CCACHE_COMPILERCHECK=content
|
||||
# Empty by default so build steps fall back to $(nproc); CI can override.
|
||||
ARG max_jobs
|
||||
ENV MAX_JOBS=${max_jobs}
|
||||
|
||||
# Install sccache if USE_SCCACHE is enabled (for release builds)
|
||||
ARG USE_SCCACHE
|
||||
ARG SCCACHE_DOWNLOAD_URL
|
||||
ARG SCCACHE_ENDPOINT
|
||||
ARG SCCACHE_BUCKET_NAME
|
||||
ARG SCCACHE_REGION_NAME
|
||||
ARG SCCACHE_S3_NO_CREDENTIALS
|
||||
RUN if [ "$USE_SCCACHE" = "1" ]; then \
|
||||
if command -v sccache >/dev/null 2>&1; then \
|
||||
echo "sccache already installed, skipping installation"; \
|
||||
sccache --version; \
|
||||
else \
|
||||
echo "Installing sccache..." \
|
||||
&& SCCACHE_ARCH="x86_64" \
|
||||
&& SCCACHE_VERSION="v0.8.1" \
|
||||
&& SCCACHE_DL_URL="${SCCACHE_DOWNLOAD_URL:-https://github.com/mozilla/sccache/releases/download/${SCCACHE_VERSION}/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl.tar.gz}" \
|
||||
&& curl -L -o /tmp/sccache.tar.gz ${SCCACHE_DL_URL} \
|
||||
&& tar -xzf /tmp/sccache.tar.gz -C /tmp \
|
||||
&& mv /tmp/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl/sccache /usr/bin/sccache \
|
||||
&& chmod +x /usr/bin/sccache \
|
||||
&& rm -rf /tmp/sccache.tar.gz /tmp/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl \
|
||||
&& sccache --version; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
# Set sccache environment variables only when USE_SCCACHE=1
|
||||
# This prevents S3 config from leaking into images when sccache is not used
|
||||
ARG USE_SCCACHE
|
||||
ENV SCCACHE_BUCKET=${USE_SCCACHE:+${SCCACHE_BUCKET_NAME}}
|
||||
ENV SCCACHE_REGION=${USE_SCCACHE:+${SCCACHE_REGION_NAME}}
|
||||
ENV SCCACHE_S3_NO_CREDENTIALS=${USE_SCCACHE:+${SCCACHE_S3_NO_CREDENTIALS}}
|
||||
ENV SCCACHE_IDLE_TIMEOUT=${USE_SCCACHE:+0}
|
||||
|
||||
ARG COMMON_WORKDIR
|
||||
WORKDIR ${COMMON_WORKDIR}
|
||||
|
||||
|
||||
# -----------------------
|
||||
# vLLM fetch stages
|
||||
FROM base AS fetch_vllm_0
|
||||
ONBUILD COPY ./ vllm/
|
||||
FROM base AS fetch_vllm_1
|
||||
ARG VLLM_REPO="https://github.com/vllm-project/vllm.git"
|
||||
ARG VLLM_BRANCH="main"
|
||||
ENV VLLM_REPO=${VLLM_REPO}
|
||||
ENV VLLM_BRANCH=${VLLM_BRANCH}
|
||||
ONBUILD RUN git clone ${VLLM_REPO} \
|
||||
&& cd vllm \
|
||||
&& git fetch -v --prune -- origin ${VLLM_BRANCH} \
|
||||
&& git checkout FETCH_HEAD \
|
||||
&& if [ ${VLLM_REPO} != "https://github.com/vllm-project/vllm.git" ] ; then \
|
||||
git remote add upstream "https://github.com/vllm-project/vllm.git" \
|
||||
&& git fetch upstream ; fi
|
||||
FROM fetch_vllm_${REMOTE_VLLM} AS fetch_vllm
|
||||
|
||||
# -----------------------
|
||||
# Rust build stage
|
||||
# Builds the `vllm-rs` frontend in a dedicated stage so the wheel build stages
|
||||
# don't need the rust toolchain or protoc.
|
||||
FROM fetch_vllm AS rust-build
|
||||
ARG COMMON_WORKDIR
|
||||
ARG USE_SCCACHE
|
||||
|
||||
# protoc is used by tonic-build/prost-build.
|
||||
RUN apt-get update -q -y && apt-get install -q -y --no-install-recommends \
|
||||
ca-certificates curl unzip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY tools/install_protoc.sh /tmp/install_protoc.sh
|
||||
RUN /tmp/install_protoc.sh && rm /tmp/install_protoc.sh
|
||||
|
||||
# Cap cargo parallelism to avoid exhausting the AMD CI host's open-file limit
|
||||
# (rustc spawns enough concurrent processes to hit RLIMIT_NOFILE otherwise).
|
||||
ENV CARGO_BUILD_JOBS=4
|
||||
ENV CARGO_NET_RETRY=10
|
||||
ENV RUSTUP_MAX_RETRIES=10
|
||||
|
||||
# BuildKit can run this stage in parallel with ROCm native builds. Keep Rust on
|
||||
# a separate local sccache daemon while sharing the same remote cache backend.
|
||||
ENV SCCACHE_SERVER_PORT=4227
|
||||
|
||||
RUN --mount=type=cache,id=vllm-rocm-uv,target=/root/.cache/uv \
|
||||
cd ${COMMON_WORKDIR}/vllm \
|
||||
&& uv pip install --system -r requirements/build/rust.txt
|
||||
|
||||
# Build the release binary. Cargo's registry/git caches can be written by
|
||||
# concurrent BuildKit jobs on shared workers, so lock those cache mounts while
|
||||
# keeping the cache benefit. Do not cache target/, because stale target metadata
|
||||
# can outlive source updates across BuildKit cache reuse.
|
||||
RUN --mount=type=cache,id=vllm-rocm-cargo-registry,target=/root/.cargo/registry,sharing=locked \
|
||||
--mount=type=cache,id=vllm-rocm-cargo-git,target=/root/.cargo/git,sharing=locked \
|
||||
cd ${COMMON_WORKDIR}/vllm \
|
||||
&& if [ "$USE_SCCACHE" = "1" ]; then \
|
||||
export RUSTC_WRAPPER=sccache \
|
||||
&& sccache --show-stats; \
|
||||
fi \
|
||||
&& bash build_rust.sh \
|
||||
&& test -x vllm/vllm-rs \
|
||||
&& if [ "$USE_SCCACHE" = "1" ]; then \
|
||||
sccache --show-stats; \
|
||||
fi
|
||||
|
||||
# -----------------------
|
||||
# vLLM native build stages
|
||||
#
|
||||
# csrc-build intentionally copies only files that affect ROCm native extension
|
||||
# compilation. That keeps unrelated CI/test/docs edits from invalidating the
|
||||
# expensive HIP/C++ build layer.
|
||||
FROM base AS csrc-build
|
||||
ARG COMMON_WORKDIR
|
||||
WORKDIR ${COMMON_WORKDIR}/vllm
|
||||
|
||||
COPY requirements/rocm.txt requirements/rocm.txt
|
||||
COPY requirements/common.txt requirements/common.txt
|
||||
RUN --mount=type=cache,id=vllm-rocm-uv,target=/root/.cache/uv \
|
||||
uv pip install --system -r requirements/rocm.txt
|
||||
|
||||
# pyproject.toml is bind-mounted in the RUN step so metadata-only changes do
|
||||
# not invalidate the expensive native build layer.
|
||||
COPY setup.py CMakeLists.txt ./
|
||||
COPY tools/build_rust.py tools/build_rust.py
|
||||
COPY cmake cmake/
|
||||
COPY csrc csrc/
|
||||
COPY vllm/envs.py vllm/envs.py
|
||||
COPY vllm/__init__.py vllm/__init__.py
|
||||
|
||||
ENV VLLM_TARGET_DEVICE=rocm
|
||||
ENV SETUPTOOLS_SCM_PRETEND_VERSION="0.0.0+rocm.csrc.build"
|
||||
|
||||
RUN --mount=type=bind,source=pyproject.toml,target=${COMMON_WORKDIR}/vllm/pyproject.toml \
|
||||
--mount=type=cache,id=vllm-rocm-ccache,target=/root/.cache/ccache \
|
||||
export CCACHE_BASEDIR="$PWD" \
|
||||
&& echo "=== ccache stats before ROCm native build ===" \
|
||||
&& (ccache --show-stats || true) \
|
||||
&& (ccache --zero-stats || true) \
|
||||
&& EFFECTIVE_MAX_JOBS="${MAX_JOBS:-$(nproc)}" \
|
||||
&& echo "Building ROCm native extension wheel with MAX_JOBS=${EFFECTIVE_MAX_JOBS}" \
|
||||
&& LDFLAGS="-fuse-ld=mold" MAX_JOBS="${EFFECTIVE_MAX_JOBS}" python3 setup.py bdist_wheel --dist-dir=dist \
|
||||
&& test -d dist \
|
||||
&& ls dist/*.whl >/dev/null \
|
||||
&& echo "=== ccache stats after ROCm native build ===" \
|
||||
&& (ccache --show-stats || true)
|
||||
|
||||
# Build the full vLLM ROCm wheel by reusing the native extension wheel from
|
||||
# csrc-build. This stage still rebuilds for Python/package changes, but skips
|
||||
# the expensive HIP/C++ compile when native inputs are unchanged.
|
||||
FROM fetch_vllm AS build_vllm
|
||||
ARG COMMON_WORKDIR
|
||||
ENV VLLM_TARGET_DEVICE=rocm
|
||||
|
||||
COPY --from=csrc-build ${COMMON_WORKDIR}/vllm/dist /precompiled-wheels
|
||||
|
||||
# Drop the pre-built Rust artifacts into the source tree. setup.py detects
|
||||
# them and ships them as-is, skipping the local Rust build.
|
||||
COPY --from=rust-build ${COMMON_WORKDIR}/vllm/vllm/vllm-rs ${COMMON_WORKDIR}/vllm/vllm/vllm-rs
|
||||
COPY --from=rust-build ${COMMON_WORKDIR}/vllm/vllm/_rust_*.so ${COMMON_WORKDIR}/vllm/vllm/
|
||||
|
||||
RUN --mount=type=cache,id=vllm-rocm-uv,target=/root/.cache/uv \
|
||||
cd vllm \
|
||||
&& uv pip install --system -r requirements/rocm.txt \
|
||||
&& export VLLM_USE_PRECOMPILED=1 \
|
||||
&& export VLLM_PRECOMPILED_WHEEL_LOCATION="$(ls /precompiled-wheels/*.whl)" \
|
||||
&& export VLLM_DOCKER_BUILD_CONTEXT=1 \
|
||||
&& echo "Packaging vLLM ROCm wheel using precompiled extensions from ${VLLM_PRECOMPILED_WHEEL_LOCATION}" \
|
||||
&& python3 setup.py bdist_wheel --dist-dir=dist \
|
||||
&& test -d dist \
|
||||
&& ls dist/*.whl >/dev/null
|
||||
FROM scratch AS export_vllm
|
||||
ARG COMMON_WORKDIR
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/dist/*.whl /
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/requirements /requirements
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/benchmarks /benchmarks
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/tests /tests
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/examples /examples
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/tools/install_torchcodec_rocm.sh /tools/install_torchcodec_rocm.sh
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/Dockerfile /docker/Dockerfile
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/Dockerfile.cpu /docker/Dockerfile.cpu
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/Dockerfile.rocm /docker/
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/Dockerfile.rocm_base /docker/Dockerfile.rocm_base
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/ci-rocm.hcl /docker/ci-rocm.hcl
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/docker-bake.hcl /docker/docker-bake.hcl
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/docker-bake-rocm.hcl /docker/docker-bake-rocm.hcl
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/.buildkite /.buildkite
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/pyproject.toml /pyproject.toml
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/rust /rust
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/rust-toolchain.toml /rust-toolchain.toml
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/vllm/v1 /vllm_v1
|
||||
|
||||
# RIXL/UCX build stages
|
||||
FROM base AS build_rixl
|
||||
ARG RIXL_BRANCH="39be1de8"
|
||||
ARG RIXL_REPO="https://github.com/ROCm/RIXL.git"
|
||||
ARG UCX_BRANCH="bfb51733"
|
||||
ARG UCX_REPO="https://github.com/openucx/ucx.git"
|
||||
ENV ROCM_PATH=/opt/rocm
|
||||
ENV UCX_HOME=/usr/local/ucx
|
||||
ENV RIXL_HOME=/usr/local/rixl
|
||||
ENV RIXL_BENCH_HOME=/usr/local/rixl_bench
|
||||
|
||||
# RIXL build system dependences and RDMA support
|
||||
RUN apt-get -y update && apt-get -y install autoconf libtool pkg-config \
|
||||
libgrpc-dev \
|
||||
libgrpc++-dev \
|
||||
libprotobuf-dev \
|
||||
protobuf-compiler-grpc \
|
||||
libcpprest-dev \
|
||||
libaio-dev \
|
||||
librdmacm1 \
|
||||
librdmacm-dev \
|
||||
libibverbs1 \
|
||||
libibverbs-dev \
|
||||
ibverbs-utils \
|
||||
rdmacm-utils \
|
||||
ibverbs-providers \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install --system meson auditwheel patchelf tomlkit
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/ccache \
|
||||
cd /usr/local/src && \
|
||||
git clone ${UCX_REPO} && \
|
||||
cd ucx && \
|
||||
git checkout ${UCX_BRANCH} && \
|
||||
./autogen.sh && \
|
||||
mkdir build && cd build && \
|
||||
CC="ccache gcc" CXX="ccache g++" \
|
||||
../configure \
|
||||
--prefix=/usr/local/ucx \
|
||||
--enable-shared \
|
||||
--disable-static \
|
||||
--disable-doxygen-doc \
|
||||
--enable-optimizations \
|
||||
--enable-devel-headers \
|
||||
--with-rocm=${ROCM_PATH} \
|
||||
--with-verbs \
|
||||
--with-dm \
|
||||
--enable-mt && \
|
||||
make -j$(nproc) && \
|
||||
make install
|
||||
|
||||
ENV PATH=/usr/local/ucx/bin:$PATH
|
||||
ENV LD_LIBRARY_PATH=${UCX_HOME}/lib:${LD_LIBRARY_PATH}
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/ccache \
|
||||
git clone ${RIXL_REPO} /opt/rixl && \
|
||||
cd /opt/rixl && \
|
||||
git checkout ${RIXL_BRANCH} && \
|
||||
CC="ccache gcc" CXX="ccache g++" \
|
||||
meson setup build --prefix=${RIXL_HOME} \
|
||||
-Ducx_path=${UCX_HOME} \
|
||||
-Drocm_path=${ROCM_PATH} && \
|
||||
cd build && \
|
||||
ninja -j$(nproc) && \
|
||||
ninja install
|
||||
|
||||
# Generate RIXL wheel
|
||||
# Exclude libcore and libpull from auditwheel: transitive dependencies
|
||||
# that are not shipped in the wheel and vary across base images.
|
||||
RUN cd /opt/rixl && \
|
||||
sed -i "s/--exclude 'libamdhip64\*'/--exclude 'libamdhip64*' --exclude 'libcore*' --exclude 'libpull*'/" \
|
||||
contrib/build-wheel.sh && \
|
||||
mkdir -p /app/install && \
|
||||
_ucx_install_dir=${UCX_HOME} \
|
||||
./contrib/build-wheel.sh \
|
||||
--output-dir /app/install \
|
||||
--rocm-dir ${ROCM_PATH} \
|
||||
--ucx-plugins-dir ${UCX_HOME}/lib/ucx \
|
||||
--nixl-plugins-dir ${RIXL_HOME}/lib/x86_64-linux-gnu/plugins
|
||||
|
||||
# ROCShmem build stage - split from DeepEP so changing DEEPEP_BRANCH does not
|
||||
# invalidate the slow ROCShmem build.
|
||||
FROM base AS build_rocshmem
|
||||
ARG ROCSHMEM_BRANCH="f0acb0c6"
|
||||
ARG ROCSHMEM_REPO="https://github.com/ROCm/rocm-systems.git"
|
||||
# DeepEP only supports gfx942 and gfx950; build ROCShmem for the same set so
|
||||
# it can be linked against DeepEP without arch mismatches.
|
||||
ARG DEEPEP_ROCM_ARCH="gfx942;gfx950"
|
||||
ENV ROCM_PATH=/opt/rocm
|
||||
ENV ROCSHMEM_DIR=/opt/rocshmem
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/ccache \
|
||||
git clone --no-checkout --filter=blob:none ${ROCSHMEM_REPO} \
|
||||
&& cd rocm-systems \
|
||||
&& git sparse-checkout set --cone projects/rocshmem \
|
||||
&& git checkout ${ROCSHMEM_BRANCH} \
|
||||
&& mkdir -p projects/rocshmem/build \
|
||||
&& cd projects/rocshmem/build \
|
||||
&& CC="ccache gcc" CXX="ccache g++" INSTALL_PREFIX=${ROCSHMEM_DIR} \
|
||||
bash ../scripts/build_configs/all_backends \
|
||||
-DROCM_PATH=${ROCM_PATH} \
|
||||
-DGPU_TARGETS="${DEEPEP_ROCM_ARCH}" \
|
||||
-DUSE_EXTERNAL_MPI=OFF
|
||||
|
||||
# DeepEP build stage - depends on ROCShmem, builds the HIP kernel wheel.
|
||||
FROM build_rocshmem AS build_deepep
|
||||
ARG DEEPEP_BRANCH="a9ea9774"
|
||||
ARG DEEPEP_REPO="https://github.com/ROCm/DeepEP.git"
|
||||
ARG DEEPEP_NIC="cx7"
|
||||
|
||||
# Build DeepEP wheel. DeepEP looks for rocshmem at ROCSHMEM_DIR.
|
||||
# DeepEP only supports gfx942 and gfx950, so avoid gfx90a in the default list.
|
||||
RUN --mount=type=cache,target=/root/.cache/ccache \
|
||||
export PYTORCH_ROCM_ARCH="gfx942;gfx950" \
|
||||
&& git clone ${DEEPEP_REPO} \
|
||||
&& cd DeepEP \
|
||||
&& git checkout ${DEEPEP_BRANCH} \
|
||||
&& LDFLAGS="-fuse-ld=mold" MAX_JOBS="${MAX_JOBS:-$(nproc)}" python3 setup.py --variant rocm --rocm-explicit-ctx --nic ${DEEPEP_NIC} bdist_wheel --dist-dir=/app/deep_install
|
||||
|
||||
# MoRI runtime dependencies live in Dockerfile.rocm so NIC backend changes do
|
||||
# not force users to rebuild the long-lived Dockerfile.rocm_base image.
|
||||
FROM base AS mori_base
|
||||
ARG NIC_BACKEND
|
||||
ARG AINIC_VERSION
|
||||
ARG UBUNTU_CODENAME
|
||||
RUN /bin/bash -lc 'set -euo pipefail; \
|
||||
\
|
||||
install_ainic() { \
|
||||
apt-get update && apt-get install -y --no-install-recommends ca-certificates curl gnupg apt-transport-https; \
|
||||
rm -rf /var/lib/apt/lists/*; \
|
||||
mkdir -p /etc/apt/keyrings; \
|
||||
curl -fsSL https://repo.radeon.com/rocm/rocm.gpg.key | gpg --dearmor > /etc/apt/keyrings/amdainic.gpg; \
|
||||
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/amdainic.gpg] https://repo.radeon.com/amdainic/pensando/ubuntu/${AINIC_VERSION} ${UBUNTU_CODENAME} main" \
|
||||
> /etc/apt/sources.list.d/amdainic.list; \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
libionic-dev \
|
||||
ionic-common \
|
||||
; \
|
||||
rm -rf /var/lib/apt/lists/*; \
|
||||
}; \
|
||||
\
|
||||
# NOTE: requires FW 235.2.86.0 and kernel drivers on the host: \
|
||||
# bnxt-en-dkms=1.10.3.235.2.86.0 bnxt-re-dkms=235.2.86.0 (from packages.broadcom.com PPA) \
|
||||
install_bnxt() { \
|
||||
install -m 0755 -d /etc/apt/keyrings; \
|
||||
curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/PackagesKey/public \
|
||||
-o /etc/apt/keyrings/broadcom-nic.asc; \
|
||||
chmod a+r /etc/apt/keyrings/broadcom-nic.asc; \
|
||||
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/broadcom-nic.asc] https://packages.broadcom.com/artifactory/ethernet-nic-debian-public jammy main" \
|
||||
> /etc/apt/sources.list.d/broadcom-nic.list; \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
bnxt-rocelib=235.2.86.0 \
|
||||
; \
|
||||
cp -a /usr/local/lib/x86_64-linux-gnu/libbnxt_re* /usr/local/lib/; \
|
||||
ldconfig; \
|
||||
rm -rf /var/lib/apt/lists/*; \
|
||||
}; \
|
||||
\
|
||||
echo "[MORI] Install MoRI proxy deps"; \
|
||||
pip install --quiet --ignore-installed blinker && \
|
||||
pip install --quiet quart msgpack aiohttp pyzmq; \
|
||||
echo "[MORI] NIC_BACKEND=${NIC_BACKEND}"; \
|
||||
\
|
||||
# NIC backend deps — mori auto-detects NIC at runtime (MORI_DEVICE_NIC env var override). \
|
||||
# Only vendor packages are installed here for dlopen; no compile-time flags needed. \
|
||||
case "${NIC_BACKEND}" in \
|
||||
none) ;; \
|
||||
all) install_ainic; install_bnxt ;; \
|
||||
ainic) install_ainic ;; \
|
||||
bnxt) install_bnxt ;; \
|
||||
*) echo "ERROR: unknown NIC_BACKEND=${NIC_BACKEND}. Use one of: none, ainic, bnxt, all"; exit 2 ;; \
|
||||
esac'
|
||||
|
||||
# -----------------------
|
||||
# vLLM wheel release build stage (for building distributable wheels)
|
||||
# This stage pins dependencies to custom ROCm wheel versions and handles version detection
|
||||
FROM fetch_vllm AS build_vllm_wheel_release
|
||||
|
||||
ARG COMMON_WORKDIR
|
||||
|
||||
# Drop the pre-built Rust artifacts into the source tree. setup.py detects
|
||||
# them and ships them as-is, skipping the local Rust build.
|
||||
COPY --from=rust-build ${COMMON_WORKDIR}/vllm/vllm/vllm-rs ${COMMON_WORKDIR}/vllm/vllm/vllm-rs
|
||||
COPY --from=rust-build ${COMMON_WORKDIR}/vllm/vllm/_rust_*.so ${COMMON_WORKDIR}/vllm/vllm/
|
||||
|
||||
# Create /install directory for custom wheels
|
||||
RUN mkdir -p /install
|
||||
|
||||
# Copy custom ROCm wheels from docker/context if they exist
|
||||
# COPY ensures Docker cache is invalidated when wheels change
|
||||
# .keep file ensures directory always exists for COPY to work
|
||||
COPY docker/context/base-wheels/ /tmp/base-wheels/
|
||||
# This is how we know if we are building for a wheel release or not.
|
||||
# If there are not wheels found there, we are not building for a wheel release.
|
||||
# So we exit with an error. To skip this stage.
|
||||
RUN if [ -n "$(ls /tmp/base-wheels/*.whl 2>/dev/null)" ]; then \
|
||||
echo "Found custom wheels - copying to /install"; \
|
||||
cp /tmp/base-wheels/*.whl /install/ && \
|
||||
echo "Copied custom wheels:"; \
|
||||
ls -lh /install/; \
|
||||
else \
|
||||
echo "ERROR: No custom wheels found in docker/context/base-wheels/"; \
|
||||
echo "Wheel releases require pre-built ROCm wheels."; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
# GIT_REPO_CHECK: Verify repo is clean and tags are available (for release builds)
|
||||
# This matches CUDA's Dockerfile behavior for proper version detection via setuptools_scm
|
||||
ARG GIT_REPO_CHECK=0
|
||||
RUN if [ "$GIT_REPO_CHECK" != "0" ]; then \
|
||||
echo "Running repository checks..."; \
|
||||
cd vllm && bash tools/check_repo.sh; \
|
||||
fi
|
||||
|
||||
# Extract version from git BEFORE any modifications (pin_rocm_dependencies.py modifies requirements/rocm.txt)
|
||||
# This ensures setuptools_scm sees clean repo state for version detection
|
||||
RUN --mount=type=bind,source=.git,target=vllm/.git \
|
||||
--mount=type=cache,target=/root/.cache/uv \
|
||||
cd vllm \
|
||||
&& uv pip install --system setuptools_scm regex \
|
||||
&& VLLM_VERSION=$(python3 -c "import setuptools_scm; print(setuptools_scm.get_version())") \
|
||||
&& echo "Detected vLLM version: ${VLLM_VERSION}" \
|
||||
&& echo "${VLLM_VERSION}" > /tmp/vllm_version.txt
|
||||
|
||||
# Fail if git-based package dependencies are found in requirements files
|
||||
# (uv doesn't handle git+ URLs well, and packages should be distributed on PyPI)
|
||||
# Extra notes: pip install is able to handle git+ URLs, but uv doesn't.
|
||||
RUN echo "Checking for git-based packages in requirements files..." \
|
||||
&& echo "Checking common.txt for git-based packages:" \
|
||||
&& if grep -q 'git+' ${COMMON_WORKDIR}/vllm/requirements/common.txt; then \
|
||||
echo "ERROR: Git-based packages found in common.txt:"; \
|
||||
grep 'git+' ${COMMON_WORKDIR}/vllm/requirements/common.txt; \
|
||||
echo "Please publish these packages to PyPI instead of using git dependencies."; \
|
||||
exit 1; \
|
||||
else \
|
||||
echo " ✓ No git-based packages found in common.txt"; \
|
||||
fi \
|
||||
&& echo "Checking rocm.txt for git-based packages:" \
|
||||
&& if grep -q 'git+' ${COMMON_WORKDIR}/vllm/requirements/rocm.txt; then \
|
||||
echo "ERROR: Git-based packages found in rocm.txt:"; \
|
||||
grep 'git+' ${COMMON_WORKDIR}/vllm/requirements/rocm.txt; \
|
||||
echo "Please publish these packages to PyPI instead of using git dependencies."; \
|
||||
exit 1; \
|
||||
else \
|
||||
echo " ✓ No git-based packages found in rocm.txt"; \
|
||||
fi \
|
||||
&& echo "All requirements files are clean - no git-based packages found"
|
||||
|
||||
# Pin vLLM dependencies to exact versions of custom ROCm wheels
|
||||
# This ensures 'pip install vllm' automatically installs correct torch/triton/torchvision/amdsmi
|
||||
COPY tools/vllm-rocm/pin_rocm_dependencies.py /tmp/pin_rocm_dependencies.py
|
||||
RUN echo "Pinning vLLM dependencies to custom wheel versions..." \
|
||||
&& python3 /tmp/pin_rocm_dependencies.py /install ${COMMON_WORKDIR}/vllm/requirements/rocm.txt
|
||||
|
||||
# Install dependencies using custom wheels from /install
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
cd vllm \
|
||||
&& echo "Building vLLM with custom wheels from /install" \
|
||||
&& uv pip install --system --find-links /install -r requirements/rocm.txt
|
||||
|
||||
# Build wheel using pre-extracted version to avoid dirty state from modified requirements/rocm.txt
|
||||
# (setup.py auto-detects ccache/sccache in PATH)
|
||||
RUN --mount=type=bind,source=.git,target=vllm/.git \
|
||||
--mount=type=cache,id=vllm-rocm-ccache,target=/root/.cache/ccache \
|
||||
cd vllm \
|
||||
&& export CCACHE_BASEDIR="$PWD" \
|
||||
&& export SETUPTOOLS_SCM_PRETEND_VERSION=$(cat /tmp/vllm_version.txt) \
|
||||
&& echo "Building wheel with version: ${SETUPTOOLS_SCM_PRETEND_VERSION}" \
|
||||
&& MAX_JOBS="${MAX_JOBS:-$(nproc)}" python3 setup.py bdist_wheel --dist-dir=dist
|
||||
|
||||
FROM scratch AS export_vllm_wheel_release
|
||||
ARG COMMON_WORKDIR
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/dist/*.whl /
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/requirements /requirements
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/benchmarks /benchmarks
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/tests /tests
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/examples /examples
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/tools/install_torchcodec_rocm.sh /tools/install_torchcodec_rocm.sh
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/Dockerfile /docker/Dockerfile
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/Dockerfile.cpu /docker/Dockerfile.cpu
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/Dockerfile.rocm /docker/
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/Dockerfile.rocm_base /docker/Dockerfile.rocm_base
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/ci-rocm.hcl /docker/ci-rocm.hcl
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/docker-bake.hcl /docker/docker-bake.hcl
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/docker-bake-rocm.hcl /docker/docker-bake-rocm.hcl
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/.buildkite /.buildkite
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/pyproject.toml /pyproject.toml
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/rust /rust
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/rust-toolchain.toml /rust-toolchain.toml
|
||||
COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/vllm/v1 /vllm_v1
|
||||
|
||||
# -----------------------
|
||||
# CI base image (Tier 1) - stable, rarely changing CI dependencies.
|
||||
# Per-PR test builds pull this as CI_BASE_IMAGE so the test stage only layers
|
||||
# in the vLLM artifacts for the current commit.
|
||||
FROM mori_base AS ci_base
|
||||
ARG COMMON_WORKDIR
|
||||
|
||||
# Update rdma-core to support latest rocshmem.
|
||||
ARG DEEPEP_NIC
|
||||
RUN if [ "${DEEPEP_NIC}" = "cx7" ] || [ "${DEEPEP_NIC}" = "io" ]; then \
|
||||
git clone --branch v62.0 --depth 1 https://github.com/linux-rdma/rdma-core.git /tmp/rdma-core && \
|
||||
cd /tmp/rdma-core && \
|
||||
mkdir -p build && cd build && \
|
||||
cmake -GNinja -DCMAKE_INSTALL_PREFIX=/usr -DNO_MAN_PAGES=1 .. && \
|
||||
ninja && ninja install && ldconfig && rm -rf /tmp/rdma-core; \
|
||||
fi
|
||||
|
||||
# Install RIXL + DeepEP wheels.
|
||||
RUN --mount=type=bind,from=build_rixl,src=/app/install,target=/rixl_install \
|
||||
--mount=type=bind,from=build_deepep,src=/app/deep_install,target=/deep_install \
|
||||
uv pip install --system /rixl_install/*.whl /deep_install/*.whl
|
||||
|
||||
# Copy ROCShmem runtime libraries.
|
||||
COPY --from=build_rocshmem /opt/rocshmem /opt/rocshmem
|
||||
|
||||
# RDMA userspace libraries plus FFmpeg dev libs needed by torchcodec.
|
||||
RUN apt-get update -q -y && apt-get install -q -y --no-install-recommends \
|
||||
librdmacm1 \
|
||||
libibverbs1 \
|
||||
ibverbs-providers \
|
||||
ibverbs-utils \
|
||||
unzip \
|
||||
pkg-config ffmpeg libavcodec-dev libavformat-dev libavutil-dev \
|
||||
libswscale-dev libavdevice-dev libavfilter-dev libswresample-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install torchcodec from source for ROCm/torch ABI compatibility.
|
||||
COPY tools/install_torchcodec_rocm.sh /tmp/install_torchcodec.sh
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=cache,target=/root/.cache/pip \
|
||||
--mount=type=cache,target=/root/.cache/torchcodec-wheels \
|
||||
bash /tmp/install_torchcodec.sh \
|
||||
&& rm /tmp/install_torchcodec.sh \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Pre-install shared ROCm runtime dependencies.
|
||||
COPY requirements/common.txt requirements/rocm.txt /tmp/ci-base-requirements/
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install --system -r /tmp/ci-base-requirements/rocm.txt \
|
||||
&& rm -rf /tmp/ci-base-requirements
|
||||
|
||||
# Enable fast and less brittle model downloads in tests.
|
||||
ENV HF_XET_HIGH_PERFORMANCE=1
|
||||
ENV HF_HUB_DOWNLOAD_TIMEOUT=60
|
||||
|
||||
# Keep torch.cuda.is_available() fork-safe (see vllm/env_override.py).
|
||||
ENV PYTORCH_NVML_BASED_CUDA_CHECK=1
|
||||
|
||||
# Pre-install vLLM test dependencies.
|
||||
COPY requirements/test/rocm.txt /tmp/rocm-test-reqs.txt
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install --system -r /tmp/rocm-test-reqs.txt
|
||||
|
||||
# Rebuild fastsafetensors from source so its C++ extension is compiled with
|
||||
# USE_ROCM and can detect libamdhip64.so at runtime.
|
||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||
FASTSAFETENSORS_REQ="$(grep -E '^fastsafetensors(==| @ )' /tmp/rocm-test-reqs.txt | head -1)" \
|
||||
&& test -n "${FASTSAFETENSORS_REQ}" \
|
||||
&& python3 -m pip install --force-reinstall --no-deps \
|
||||
--no-binary fastsafetensors "${FASTSAFETENSORS_REQ}" \
|
||||
&& rm /tmp/rocm-test-reqs.txt
|
||||
|
||||
# Set MIOPEN ENVS to resolve performance regressions in MIOpen 3D convolution kernel.
|
||||
# See: https://github.com/pytorch/pytorch/issues/169857
|
||||
ENV MIOPEN_DEBUG_CONV_DIRECT=0
|
||||
ENV MIOPEN_DEBUG_CONV_GEMM=0
|
||||
|
||||
# Use legacy IPC mode for HSA to avoid GPU memory pinning issues with UCX rocm_ipc.
|
||||
# See: https://github.com/ROCm/rocm-libraries/issues/6266
|
||||
ENV HSA_ENABLE_IPC_MODE_LEGACY=1
|
||||
|
||||
# ROCm profiler limits workaround.
|
||||
RUN echo "ROCTRACER_MAX_EVENTS=10000000" > ${COMMON_WORKDIR}/libkineto.conf
|
||||
ENV KINETO_CONFIG="${COMMON_WORKDIR}/libkineto.conf"
|
||||
|
||||
# Install vllm_test_utils in ci_base for ci_base + wheel parity.
|
||||
COPY tests/vllm_test_utils /tmp/vllm_test_utils
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install --system /tmp/vllm_test_utils \
|
||||
&& rm -rf /tmp/vllm_test_utils
|
||||
|
||||
# -----------------------
|
||||
# Test vLLM image (Tier 2) - vLLM-only layer on top of ci_base.
|
||||
FROM ${CI_BASE_IMAGE} AS test
|
||||
ARG COMMON_WORKDIR
|
||||
|
||||
# Install the vLLM wheel (--no-deps: all deps already in ci_base).
|
||||
RUN --mount=type=bind,from=export_vllm,src=/,target=/install \
|
||||
--mount=type=cache,target=/root/.cache/uv \
|
||||
cd /install \
|
||||
&& uv pip install --system --no-deps *.whl
|
||||
|
||||
# Store the vLLM wheel in the image for python-only install tests.
|
||||
COPY --from=export_vllm /*.whl /opt/vllm-wheels/
|
||||
|
||||
WORKDIR /vllm-workspace
|
||||
COPY --from=build_vllm ${COMMON_WORKDIR}/vllm /vllm-workspace
|
||||
|
||||
# Copy in the v1 package (for python-only install test group).
|
||||
COPY --from=export_vllm /vllm_v1 /usr/local/lib/python${PYTHON_VERSION}/dist-packages/vllm/v1
|
||||
|
||||
# Hide source under src/ so it won't shadow the installed package in tests.
|
||||
RUN mkdir src && mv vllm src/vllm
|
||||
|
||||
# -----------------------
|
||||
# Final vLLM image
|
||||
FROM mori_base AS final
|
||||
|
||||
RUN python3 -m pip install --upgrade pip && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Clean up sccache from release image (not needed at runtime)
|
||||
# This removes the binary and wrappers that may have been installed during build
|
||||
RUN rm -f /usr/bin/sccache || true \
|
||||
&& rm -rf /opt/sccache-wrappers || true
|
||||
|
||||
# Unset sccache environment variables for the release image
|
||||
# This prevents S3 bucket config from leaking into production images
|
||||
ENV SCCACHE_BUCKET=
|
||||
ENV SCCACHE_REGION=
|
||||
ENV SCCACHE_ENDPOINT=
|
||||
ENV SCCACHE_S3_NO_CREDENTIALS=
|
||||
ENV SCCACHE_IDLE_TIMEOUT=
|
||||
|
||||
# Error related to odd state for numpy 1.20.3 where there is no METADATA etc, but an extra LICENSES_bundled.txt.
|
||||
# Manually remove it so that later steps of numpy upgrade can continue
|
||||
RUN case "$(which python3)" in \
|
||||
*"/opt/conda/envs/py_3.9"*) \
|
||||
rm -rf /opt/conda/envs/py_3.9/lib/python3.9/site-packages/numpy-1.20.3.dist-info/;; \
|
||||
*) ;; esac
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install --system --upgrade huggingface-hub[cli]
|
||||
|
||||
# Install vLLM using uv (inherited from base stage)
|
||||
# Note: No -U flag to avoid upgrading PyTorch ROCm to CUDA version
|
||||
RUN --mount=type=bind,from=export_vllm,src=/,target=/install \
|
||||
--mount=type=cache,target=/root/.cache/uv \
|
||||
cd /install \
|
||||
&& uv pip install --system -r requirements/rocm.txt \
|
||||
&& pip uninstall -y vllm \
|
||||
&& uv pip install --system *.whl
|
||||
|
||||
# Install RIXL wheel
|
||||
RUN --mount=type=bind,from=build_rixl,src=/app/install,target=/rixl_install \
|
||||
uv pip install --system /rixl_install/*.whl
|
||||
|
||||
ARG COMMON_WORKDIR
|
||||
ARG BASE_IMAGE
|
||||
ARG NIC_BACKEND
|
||||
ARG AINIC_VERSION
|
||||
|
||||
# Copy over the benchmark scripts as well
|
||||
COPY --from=export_vllm /benchmarks ${COMMON_WORKDIR}/vllm/benchmarks
|
||||
COPY --from=export_vllm /examples ${COMMON_WORKDIR}/vllm/examples
|
||||
COPY --from=export_vllm /docker ${COMMON_WORKDIR}/vllm/docker
|
||||
|
||||
# Use legacy IPC mode for HSA to avoid GPU memory pinning issues with UCX rocm_ipc
|
||||
# See: https://github.com/ROCm/rocm-libraries/issues/6266
|
||||
ENV HSA_ENABLE_IPC_MODE_LEGACY=1
|
||||
|
||||
ENV TOKENIZERS_PARALLELISM=false
|
||||
|
||||
# ENV that can improve safe tensor loading, and end-to-end time
|
||||
ENV SAFETENSORS_FAST_GPU=1
|
||||
|
||||
# Performance environment variable.
|
||||
ENV HIP_FORCE_DEV_KERNARG=1
|
||||
|
||||
# Keep torch.cuda.is_available() fork-safe (see vllm/env_override.py).
|
||||
ENV PYTORCH_NVML_BASED_CUDA_CHECK=1
|
||||
|
||||
# Workaround for ROCm profiler limits
|
||||
RUN echo "ROCTRACER_MAX_EVENTS=10000000" > ${COMMON_WORKDIR}/libkineto.conf
|
||||
ENV KINETO_CONFIG="${COMMON_WORKDIR}/libkineto.conf"
|
||||
RUN echo "VLLM_BASE_IMAGE=${BASE_IMAGE}" >> ${COMMON_WORKDIR}/versions.txt \
|
||||
&& echo "MORI_NIC_BACKEND=${NIC_BACKEND}" >> ${COMMON_WORKDIR}/versions.txt \
|
||||
&& echo "AINIC_VERSION=${AINIC_VERSION}" >> ${COMMON_WORKDIR}/versions.txt
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
|
||||
#Set entrypoint for vllm-openai official images
|
||||
FROM final AS vllm-openai
|
||||
ENTRYPOINT ["vllm", "serve"]
|
||||
@@ -0,0 +1,321 @@
|
||||
ARG BASE_IMAGE=rocm/dev-ubuntu-22.04:7.2.3-complete
|
||||
ARG TRITON_BRANCH="0f380657"
|
||||
ARG TRITON_REPO="https://github.com/ROCm/triton.git"
|
||||
ARG PYTORCH_BRANCH="d0c8b1f3" # release/2.11 as of 6/09
|
||||
ARG PYTORCH_REPO="https://github.com/ROCm/pytorch.git"
|
||||
ARG PYTORCH_VISION_BRANCH="v0.24.1"
|
||||
ARG PYTORCH_VISION_REPO="https://github.com/pytorch/vision.git"
|
||||
ARG PYTORCH_AUDIO_BRANCH="v2.9.0"
|
||||
ARG PYTORCH_AUDIO_REPO="https://github.com/pytorch/audio.git"
|
||||
ARG FA_BRANCH="0e60e394"
|
||||
ARG FA_REPO="https://github.com/Dao-AILab/flash-attention.git"
|
||||
ARG AITER_BRANCH="v0.1.16.post3"
|
||||
ARG AITER_REPO="https://github.com/ROCm/aiter.git"
|
||||
ARG MORI_BRANCH="v1.1.0"
|
||||
ARG MORI_REPO="https://github.com/ROCm/mori.git"
|
||||
|
||||
# Sccache configuration (only used in release pipeline)
|
||||
ARG USE_SCCACHE
|
||||
ARG SCCACHE_DOWNLOAD_URL
|
||||
ARG SCCACHE_ENDPOINT
|
||||
ARG SCCACHE_BUCKET_NAME=vllm-build-sccache
|
||||
ARG SCCACHE_REGION_NAME=us-west-2
|
||||
ARG SCCACHE_S3_NO_CREDENTIALS=0
|
||||
|
||||
FROM ${BASE_IMAGE} AS base
|
||||
|
||||
ENV PATH=/opt/rocm/llvm/bin:/opt/rocm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
ENV ROCM_PATH=/opt/rocm
|
||||
ENV LD_LIBRARY_PATH=/opt/rocm/lib:/usr/local/lib:
|
||||
ARG PYTORCH_ROCM_ARCH=gfx90a;gfx942;gfx950;gfx1100;gfx1101;gfx1200;gfx1201;gfx1150;gfx1151
|
||||
ENV PYTORCH_ROCM_ARCH=${PYTORCH_ROCM_ARCH}
|
||||
ENV AITER_ROCM_ARCH=gfx942;gfx950
|
||||
ENV MORI_GPU_ARCHS=gfx942;gfx950
|
||||
|
||||
# Required for RCCL in ROCm7.1
|
||||
ENV HSA_NO_SCRATCH_RECLAIM=1
|
||||
|
||||
ARG PYTHON_VERSION=3.12
|
||||
ENV PYTHON_VERSION=${PYTHON_VERSION}
|
||||
|
||||
RUN mkdir -p /app
|
||||
WORKDIR /app
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Install Python and other dependencies
|
||||
RUN apt-get update -y \
|
||||
&& apt-get install -y software-properties-common git curl sudo vim less libgfortran5 libopenmpi-dev libpci-dev liblzma-dev pkg-config \
|
||||
&& for i in 1 2 3; do \
|
||||
add-apt-repository -y ppa:deadsnakes/ppa && break || \
|
||||
{ echo "Attempt $i failed, retrying in 5s..."; sleep 5; }; \
|
||||
done \
|
||||
&& apt-get update -y \
|
||||
&& apt-get install -y python${PYTHON_VERSION} python${PYTHON_VERSION}-dev python${PYTHON_VERSION}-venv \
|
||||
python${PYTHON_VERSION}-lib2to3 python-is-python3 \
|
||||
&& update-alternatives --install /usr/bin/python3 python3 /usr/bin/python${PYTHON_VERSION} 1 \
|
||||
&& update-alternatives --set python3 /usr/bin/python${PYTHON_VERSION} \
|
||||
&& ln -sf /usr/bin/python${PYTHON_VERSION}-config /usr/bin/python3-config \
|
||||
&& curl -sS https://bootstrap.pypa.io/get-pip.py | python${PYTHON_VERSION} \
|
||||
&& python3 --version && python3 -m pip --version
|
||||
|
||||
RUN pip install -U packaging 'cmake<4' ninja wheel 'setuptools<80' pybind11 Cython
|
||||
RUN apt-get update && apt-get install -y libjpeg-dev libsox-dev libsox-fmt-all sox && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install sccache if USE_SCCACHE is enabled (for release builds)
|
||||
ARG USE_SCCACHE
|
||||
ARG SCCACHE_DOWNLOAD_URL
|
||||
ARG SCCACHE_ENDPOINT
|
||||
ARG SCCACHE_BUCKET_NAME
|
||||
ARG SCCACHE_REGION_NAME
|
||||
ARG SCCACHE_S3_NO_CREDENTIALS
|
||||
RUN if [ "$USE_SCCACHE" = "1" ]; then \
|
||||
echo "Installing sccache..." \
|
||||
&& SCCACHE_ARCH="x86_64" \
|
||||
&& SCCACHE_VERSION="v0.8.1" \
|
||||
&& SCCACHE_DL_URL="${SCCACHE_DOWNLOAD_URL:-https://github.com/mozilla/sccache/releases/download/${SCCACHE_VERSION}/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl.tar.gz}" \
|
||||
&& curl -L -o /tmp/sccache.tar.gz ${SCCACHE_DL_URL} \
|
||||
&& tar -xzf /tmp/sccache.tar.gz -C /tmp \
|
||||
&& mv /tmp/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl/sccache /usr/bin/sccache \
|
||||
&& chmod +x /usr/bin/sccache \
|
||||
&& rm -rf /tmp/sccache.tar.gz /tmp/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl \
|
||||
&& sccache --version; \
|
||||
fi
|
||||
|
||||
# Setup sccache for HIP compilation via HIP_CLANG_PATH
|
||||
# This creates wrapper scripts in a separate directory and points HIP to use them
|
||||
# This avoids modifying the original ROCm binaries which can break detection
|
||||
# NOTE: HIP_CLANG_PATH is NOT set as ENV to avoid affecting downstream images (Dockerfile.rocm)
|
||||
# Instead, each build stage should export HIP_CLANG_PATH=/opt/sccache-wrappers if USE_SCCACHE=1
|
||||
RUN if [ "$USE_SCCACHE" = "1" ]; then \
|
||||
echo "Setting up sccache wrappers for HIP compilation..." \
|
||||
&& mkdir -p /opt/sccache-wrappers \
|
||||
&& printf '#!/bin/bash\nexec sccache /opt/rocm/lib/llvm/bin/clang++ "$@"\n' > /opt/sccache-wrappers/clang++ \
|
||||
&& chmod +x /opt/sccache-wrappers/clang++ \
|
||||
&& printf '#!/bin/bash\nexec sccache /opt/rocm/lib/llvm/bin/clang "$@"\n' > /opt/sccache-wrappers/clang \
|
||||
&& chmod +x /opt/sccache-wrappers/clang \
|
||||
&& echo "sccache wrappers created in /opt/sccache-wrappers"; \
|
||||
fi
|
||||
|
||||
# Set sccache environment variables only when USE_SCCACHE=1
|
||||
# This prevents S3 config from leaking into images when sccache is not used
|
||||
ARG USE_SCCACHE
|
||||
ENV SCCACHE_BUCKET=${USE_SCCACHE:+${SCCACHE_BUCKET_NAME}}
|
||||
ENV SCCACHE_REGION=${USE_SCCACHE:+${SCCACHE_REGION_NAME}}
|
||||
ENV SCCACHE_S3_NO_CREDENTIALS=${USE_SCCACHE:+${SCCACHE_S3_NO_CREDENTIALS}}
|
||||
ENV SCCACHE_IDLE_TIMEOUT=${USE_SCCACHE:+0}
|
||||
|
||||
|
||||
###
|
||||
### Triton Build
|
||||
###
|
||||
FROM base AS build_triton
|
||||
ARG TRITON_BRANCH
|
||||
ARG TRITON_REPO
|
||||
RUN git clone ${TRITON_REPO}
|
||||
# Cherry picking the following
|
||||
# https://github.com/triton-lang/triton/pull/8991
|
||||
RUN cd triton \
|
||||
&& git checkout ${TRITON_BRANCH} \
|
||||
&& git config --global user.email "you@example.com" && git config --global user.name "Your Name" \
|
||||
&& git cherry-pick 555d04f \
|
||||
&& if [ ! -f setup.py ]; then cd python; fi \
|
||||
&& python3 setup.py bdist_wheel --dist-dir=dist \
|
||||
&& mkdir -p /app/install && cp dist/*.whl /app/install
|
||||
RUN if [ -d triton/python/triton_kernels ]; then pip install build && cd triton/python/triton_kernels \
|
||||
&& python3 -m build --wheel && cp dist/*.whl /app/install; fi
|
||||
|
||||
|
||||
###
|
||||
### AMD SMI Build
|
||||
###
|
||||
FROM base AS build_amdsmi
|
||||
RUN cd /opt/rocm/share/amd_smi \
|
||||
&& pip wheel . --wheel-dir=dist
|
||||
RUN mkdir -p /app/install && cp /opt/rocm/share/amd_smi/dist/*.whl /app/install
|
||||
|
||||
|
||||
###
|
||||
### Pytorch build
|
||||
###
|
||||
FROM base AS build_pytorch
|
||||
ARG PYTORCH_BRANCH
|
||||
ARG PYTORCH_VISION_BRANCH
|
||||
ARG PYTORCH_AUDIO_BRANCH
|
||||
ARG PYTORCH_REPO
|
||||
ARG PYTORCH_VISION_REPO
|
||||
ARG PYTORCH_AUDIO_REPO
|
||||
ARG USE_SCCACHE
|
||||
|
||||
RUN apt-get update && apt-get install -y pkg-config liblzma-dev
|
||||
RUN git clone ${PYTORCH_REPO} pytorch
|
||||
RUN cd pytorch && git checkout ${PYTORCH_BRANCH}
|
||||
RUN cd pytorch \
|
||||
&& pip install -r requirements.txt && git submodule update --init --recursive
|
||||
RUN cd pytorch && python3 tools/amd_build/build_amd.py \
|
||||
&& if [ "$USE_SCCACHE" = "1" ]; then \
|
||||
export HIP_CLANG_PATH=/opt/sccache-wrappers \
|
||||
&& export CMAKE_C_COMPILER_LAUNCHER=sccache \
|
||||
&& export CMAKE_CXX_COMPILER_LAUNCHER=sccache \
|
||||
&& sccache --show-stats; \
|
||||
fi \
|
||||
&& CMAKE_PREFIX_PATH=$(python3 -c 'import sys; print(sys.prefix)') python3 setup.py bdist_wheel --dist-dir=dist \
|
||||
&& if [ "$USE_SCCACHE" = "1" ]; then sccache --show-stats; fi \
|
||||
&& pip install dist/*.whl
|
||||
RUN git clone ${PYTORCH_VISION_REPO} vision
|
||||
RUN cd vision && git checkout ${PYTORCH_VISION_BRANCH} \
|
||||
&& if [ "$USE_SCCACHE" = "1" ]; then \
|
||||
export HIP_CLANG_PATH=/opt/sccache-wrappers \
|
||||
&& export CMAKE_C_COMPILER_LAUNCHER=sccache \
|
||||
&& export CMAKE_CXX_COMPILER_LAUNCHER=sccache; \
|
||||
fi \
|
||||
&& python3 setup.py bdist_wheel --dist-dir=dist \
|
||||
&& if [ "$USE_SCCACHE" = "1" ]; then sccache --show-stats; fi \
|
||||
&& pip install dist/*.whl
|
||||
RUN git clone ${PYTORCH_AUDIO_REPO} audio
|
||||
RUN cd audio && git checkout ${PYTORCH_AUDIO_BRANCH} \
|
||||
&& git submodule update --init --recursive \
|
||||
&& pip install -r requirements.txt \
|
||||
&& if [ "$USE_SCCACHE" = "1" ]; then \
|
||||
export HIP_CLANG_PATH=/opt/sccache-wrappers \
|
||||
&& export CMAKE_C_COMPILER_LAUNCHER=sccache \
|
||||
&& export CMAKE_CXX_COMPILER_LAUNCHER=sccache; \
|
||||
fi \
|
||||
&& python3 setup.py bdist_wheel --dist-dir=dist \
|
||||
&& if [ "$USE_SCCACHE" = "1" ]; then sccache --show-stats; fi \
|
||||
&& pip install dist/*.whl
|
||||
RUN mkdir -p /app/install && cp /app/pytorch/dist/*.whl /app/install \
|
||||
&& cp /app/vision/dist/*.whl /app/install \
|
||||
&& cp /app/audio/dist/*.whl /app/install
|
||||
|
||||
|
||||
###
|
||||
### MORI Build
|
||||
###
|
||||
FROM base AS build_mori
|
||||
ARG MORI_BRANCH
|
||||
ARG MORI_REPO
|
||||
RUN --mount=type=bind,from=build_pytorch,src=/app/install/,target=/install \
|
||||
pip install /install/*.whl
|
||||
RUN git clone ${MORI_REPO}
|
||||
RUN cd mori \
|
||||
&& git checkout ${MORI_BRANCH} \
|
||||
&& git submodule update --init --recursive \
|
||||
&& python3 setup.py bdist_wheel --dist-dir=dist && ls /app/mori/dist/*.whl
|
||||
RUN mkdir -p /app/install && cp /app/mori/dist/*.whl /app/install
|
||||
|
||||
|
||||
###
|
||||
### FlashAttention Build
|
||||
###
|
||||
FROM base AS build_fa
|
||||
ARG FA_BRANCH
|
||||
ARG FA_REPO
|
||||
ARG USE_SCCACHE
|
||||
RUN --mount=type=bind,from=build_pytorch,src=/app/install/,target=/install \
|
||||
pip install /install/*.whl
|
||||
RUN git clone ${FA_REPO}
|
||||
RUN cd flash-attention \
|
||||
&& git checkout ${FA_BRANCH} \
|
||||
&& git submodule update --init \
|
||||
&& if [ "$USE_SCCACHE" = "1" ]; then \
|
||||
export HIP_CLANG_PATH=/opt/sccache-wrappers \
|
||||
&& sccache --show-stats; \
|
||||
fi \
|
||||
&& GPU_ARCHS=$(echo ${PYTORCH_ROCM_ARCH} | sed -e 's/;gfx1[0-9]\{3\}//g') python3 setup.py bdist_wheel --dist-dir=dist \
|
||||
&& if [ "$USE_SCCACHE" = "1" ]; then sccache --show-stats; fi
|
||||
RUN mkdir -p /app/install && cp /app/flash-attention/dist/*.whl /app/install
|
||||
|
||||
|
||||
###
|
||||
### AITER Build
|
||||
###
|
||||
FROM base AS build_aiter
|
||||
ARG AITER_BRANCH
|
||||
ARG AITER_REPO
|
||||
ARG USE_SCCACHE
|
||||
RUN --mount=type=bind,from=build_pytorch,src=/app/install/,target=/install \
|
||||
pip install /install/*.whl
|
||||
RUN git clone --recursive --branch ${AITER_BRANCH} ${AITER_REPO}
|
||||
RUN cd aiter \
|
||||
&& git submodule update --init --recursive \
|
||||
&& pip install -r requirements.txt
|
||||
RUN pip install pyyaml && cd aiter \
|
||||
&& if [ "$USE_SCCACHE" = "1" ]; then \
|
||||
export HIP_CLANG_PATH=/opt/sccache-wrappers \
|
||||
&& sccache --show-stats; \
|
||||
fi \
|
||||
&& PREBUILD_KERNELS=1 AITER_USE_SYSTEM_TRITON=1 GPU_ARCHS=${AITER_ROCM_ARCH} python3 setup.py bdist_wheel --dist-dir=dist \
|
||||
&& if [ "$USE_SCCACHE" = "1" ]; then sccache --show-stats; fi \
|
||||
&& ls /app/aiter/dist/*.whl
|
||||
RUN mkdir -p /app/install && cp /app/aiter/dist/*.whl /app/install
|
||||
|
||||
|
||||
###
|
||||
### Final Build
|
||||
###
|
||||
|
||||
# Wheel release stage -
|
||||
# only includes dependencies used by wheel release pipeline
|
||||
FROM base AS debs_wheel_release
|
||||
RUN mkdir /app/debs
|
||||
RUN --mount=type=bind,from=build_triton,src=/app/install/,target=/install \
|
||||
cp /install/*.whl /app/debs
|
||||
RUN --mount=type=bind,from=build_fa,src=/app/install/,target=/install \
|
||||
cp /install/*.whl /app/debs
|
||||
RUN --mount=type=bind,from=build_amdsmi,src=/app/install/,target=/install \
|
||||
cp /install/*.whl /app/debs
|
||||
RUN --mount=type=bind,from=build_pytorch,src=/app/install/,target=/install \
|
||||
cp /install/*.whl /app/debs
|
||||
RUN --mount=type=bind,from=build_aiter,src=/app/install/,target=/install \
|
||||
cp /install/*.whl /app/debs
|
||||
|
||||
# Full debs stage - includes Mori (used by Docker releases)
|
||||
FROM base AS debs
|
||||
RUN mkdir /app/debs
|
||||
RUN --mount=type=bind,from=build_triton,src=/app/install/,target=/install \
|
||||
cp /install/*.whl /app/debs
|
||||
RUN --mount=type=bind,from=build_fa,src=/app/install/,target=/install \
|
||||
cp /install/*.whl /app/debs
|
||||
RUN --mount=type=bind,from=build_amdsmi,src=/app/install/,target=/install \
|
||||
cp /install/*.whl /app/debs
|
||||
RUN --mount=type=bind,from=build_pytorch,src=/app/install/,target=/install \
|
||||
cp /install/*.whl /app/debs
|
||||
RUN --mount=type=bind,from=build_aiter,src=/app/install/,target=/install \
|
||||
cp /install/*.whl /app/debs
|
||||
RUN --mount=type=bind,from=build_mori,src=/app/install/,target=/install \
|
||||
cp /install/*.whl /app/debs
|
||||
|
||||
FROM base AS final
|
||||
RUN --mount=type=bind,from=debs,src=/app/debs,target=/install \
|
||||
pip install /install/*.whl
|
||||
|
||||
ARG BASE_IMAGE
|
||||
ARG TRITON_BRANCH
|
||||
ARG TRITON_REPO
|
||||
ARG PYTORCH_BRANCH
|
||||
ARG PYTORCH_VISION_BRANCH
|
||||
ARG PYTORCH_REPO
|
||||
ARG PYTORCH_VISION_REPO
|
||||
ARG PYTORCH_AUDIO_BRANCH
|
||||
ARG PYTORCH_AUDIO_REPO
|
||||
ARG FA_BRANCH
|
||||
ARG FA_REPO
|
||||
ARG AITER_BRANCH
|
||||
ARG AITER_REPO
|
||||
ARG MORI_BRANCH
|
||||
ARG MORI_REPO
|
||||
RUN echo "BASE_IMAGE: ${BASE_IMAGE}" > /app/versions.txt \
|
||||
&& echo "TRITON_BRANCH: ${TRITON_BRANCH}" >> /app/versions.txt \
|
||||
&& echo "TRITON_REPO: ${TRITON_REPO}" >> /app/versions.txt \
|
||||
&& echo "PYTORCH_BRANCH: ${PYTORCH_BRANCH}" >> /app/versions.txt \
|
||||
&& echo "PYTORCH_VISION_BRANCH: ${PYTORCH_VISION_BRANCH}" >> /app/versions.txt \
|
||||
&& echo "PYTORCH_REPO: ${PYTORCH_REPO}" >> /app/versions.txt \
|
||||
&& echo "PYTORCH_VISION_REPO: ${PYTORCH_VISION_REPO}" >> /app/versions.txt \
|
||||
&& echo "PYTORCH_AUDIO_BRANCH: ${PYTORCH_AUDIO_BRANCH}" >> /app/versions.txt \
|
||||
&& echo "PYTORCH_AUDIO_REPO: ${PYTORCH_AUDIO_REPO}" >> /app/versions.txt \
|
||||
&& echo "FA_BRANCH: ${FA_BRANCH}" >> /app/versions.txt \
|
||||
&& echo "FA_REPO: ${FA_REPO}" >> /app/versions.txt \
|
||||
&& echo "AITER_BRANCH: ${AITER_BRANCH}" >> /app/versions.txt \
|
||||
&& echo "AITER_REPO: ${AITER_REPO}" >> /app/versions.txt \
|
||||
&& echo "MORI_BRANCH: ${MORI_BRANCH}" >> /app/versions.txt \
|
||||
&& echo "MORI_REPO: ${MORI_REPO}" >> /app/versions.txt
|
||||
@@ -0,0 +1,288 @@
|
||||
# Base UBI image for s390x architecture
|
||||
ARG BASE_UBI_IMAGE_TAG=9.6
|
||||
ARG PYTHON_VERSION=3.12
|
||||
FROM registry.access.redhat.com/ubi9/ubi-minimal:${BASE_UBI_IMAGE_TAG} AS base
|
||||
|
||||
# Install basic dependencies
|
||||
ARG PYTHON_VERSION
|
||||
ENV PYTHON_VERSION=${PYTHON_VERSION}
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
ENV LANG=C.UTF-8 \
|
||||
LC_ALL=C.UTF-8
|
||||
|
||||
# Install development utilities
|
||||
RUN microdnf install -y \
|
||||
which procps findutils tar vim git gcc-toolset-14 gcc-toolset-14-binutils gcc-toolset-14-libatomic-devel patch zlib-devel \
|
||||
libjpeg-turbo-devel libtiff-devel libpng-devel libwebp-devel freetype-devel harfbuzz-devel \
|
||||
openssl-devel openblas openblas-devel autoconf automake libtool cmake numpy libsndfile \
|
||||
clang llvm-devel llvm-static clang-devel && \
|
||||
microdnf clean all
|
||||
|
||||
ENV GCC_TOOLSET_ROOT=/opt/rh/gcc-toolset-14/root \
|
||||
PATH=/opt/rh/gcc-toolset-14/root/usr/bin:/usr/local/bin:/usr/bin:/bin \
|
||||
LD_LIBRARY_PATH=/opt/rh/gcc-toolset-14/root/usr/lib64:/usr/local/lib:/usr/lib64 \
|
||||
LIBRARY_PATH=/opt/rh/gcc-toolset-14/root/usr/lib64 \
|
||||
PKG_CONFIG_PATH=/opt/rh/gcc-toolset-14/root/usr/lib64/pkgconfig
|
||||
|
||||
# Python Installation
|
||||
FROM base AS python-install
|
||||
ARG PYTHON_VERSION
|
||||
|
||||
ENV VIRTUAL_ENV=/opt/vllm
|
||||
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
|
||||
ENV PYTHON_VERSION=${PYTHON_VERSION}
|
||||
RUN microdnf install -y \
|
||||
python${PYTHON_VERSION}-devel python${PYTHON_VERSION}-pip python${PYTHON_VERSION}-wheel && \
|
||||
python${PYTHON_VERSION} -m venv $VIRTUAL_ENV && pip install --no-cache -U pip wheel uv && microdnf clean all
|
||||
|
||||
FROM python-install AS pyarrow
|
||||
|
||||
# Build Apache Arrow
|
||||
WORKDIR /tmp
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
git clone https://github.com/apache/arrow.git -b maint-19.0.1 && \
|
||||
cd arrow/cpp && \
|
||||
mkdir release && cd release && \
|
||||
cmake -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||
-DARROW_PYTHON=ON \
|
||||
-DARROW_PARQUET=ON \
|
||||
-DARROW_ORC=ON \
|
||||
-DARROW_FILESYSTEM=ON \
|
||||
-DARROW_WITH_LZ4=ON \
|
||||
-DARROW_WITH_ZSTD=ON \
|
||||
-DARROW_WITH_SNAPPY=ON \
|
||||
-DARROW_JSON=ON \
|
||||
-DARROW_CSV=ON \
|
||||
-DARROW_DATASET=ON \
|
||||
-DPROTOBUF_PROTOC_EXECUTABLE=/usr/bin/protoc \
|
||||
-DARROW_DEPENDENCY_SOURCE=BUNDLED \
|
||||
.. && \
|
||||
make -j$(nproc) && \
|
||||
make install && \
|
||||
cd ../../python && \
|
||||
export PYARROW_PARALLEL=4 && \
|
||||
export ARROW_BUILD_TYPE=release && \
|
||||
uv pip install -r requirements-build.txt && \
|
||||
python setup.py build_ext --build-type=$ARROW_BUILD_TYPE --bundle-arrow-cpp bdist_wheel
|
||||
|
||||
FROM python-install AS rust
|
||||
ENV CARGO_HOME=/root/.cargo
|
||||
ENV RUSTUP_HOME=/root/.rustup
|
||||
ENV PATH="$CARGO_HOME/bin:$RUSTUP_HOME/bin:$PATH"
|
||||
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y && \
|
||||
. "$CARGO_HOME/env" && \
|
||||
rustup default stable && \
|
||||
rustup show
|
||||
|
||||
FROM python-install AS numa-build
|
||||
WORKDIR /tmp
|
||||
RUN curl -LO https://github.com/numactl/numactl/archive/refs/tags/v2.0.19.tar.gz && \
|
||||
tar -xvzf v2.0.19.tar.gz && \
|
||||
cd numactl-2.0.19 && \
|
||||
./autogen.sh && \
|
||||
./configure && \
|
||||
make
|
||||
|
||||
# Set include path
|
||||
ENV C_INCLUDE_PATH="/usr/local/include:$C_INCLUDE_PATH"
|
||||
|
||||
FROM python-install AS torch-vision
|
||||
# Install torchvision
|
||||
ARG TORCH_VISION_VERSION=v0.26.0
|
||||
WORKDIR /tmp
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
git clone https://github.com/pytorch/vision.git && \
|
||||
cd vision && \
|
||||
git checkout $TORCH_VISION_VERSION && \
|
||||
uv pip install torch==2.11.0 --index-url https://download.pytorch.org/whl/cpu && \
|
||||
python setup.py bdist_wheel
|
||||
|
||||
FROM python-install AS hf-xet-builder
|
||||
# Install hf-xet
|
||||
WORKDIR /tmp
|
||||
ENV CARGO_HOME=/root/.cargo
|
||||
ENV RUSTUP_HOME=/root/.rustup
|
||||
ENV PATH="$CARGO_HOME/bin:$RUSTUP_HOME/bin:$PATH"
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=bind,from=rust,source=/root/.cargo,target=/root/.cargo,rw \
|
||||
--mount=type=bind,from=rust,source=/root/.rustup,target=/root/.rustup,rw \
|
||||
git clone https://github.com/huggingface/xet-core.git && \
|
||||
cd xet-core/hf_xet/ && \
|
||||
uv pip install maturin patchelf && \
|
||||
python -m maturin build --release --out dist && \
|
||||
mkdir -p /tmp/hf-xet/dist && \
|
||||
cp dist/*.whl /tmp/hf-xet/dist/
|
||||
|
||||
# Build numba
|
||||
FROM python-install AS numba-builder
|
||||
|
||||
ARG MAX_JOBS
|
||||
ARG NUMBA_VERSION=0.61.2
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
# Clone all required dependencies
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
microdnf install ninja-build gcc gcc-c++ -y && \
|
||||
git clone --recursive https://github.com/llvm/llvm-project.git -b llvmorg-15.0.7 && \
|
||||
git clone --recursive https://github.com/numba/llvmlite.git -b v0.44.0 && \
|
||||
git clone --recursive https://github.com/numba/numba.git -b ${NUMBA_VERSION} && \
|
||||
cd llvm-project && mkdir build && cd build && \
|
||||
uv pip install 'cmake<4' 'setuptools<70' numpy && \
|
||||
export PREFIX=/usr/local && CMAKE_ARGS="${CMAKE_ARGS} -DLLVM_ENABLE_PROJECTS=lld;libunwind;compiler-rt" \
|
||||
CFLAGS="$(echo $CFLAGS | sed 's/-fno-plt //g')" \
|
||||
CXXFLAGS="$(echo $CXXFLAGS | sed 's/-fno-plt //g')" \
|
||||
CMAKE_ARGS="${CMAKE_ARGS} -DFFI_INCLUDE_DIR=$PREFIX/include" \
|
||||
CMAKE_ARGS="${CMAKE_ARGS} -DFFI_LIBRARY_DIR=$PREFIX/lib" \
|
||||
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_LIBRARY_PATH="${PREFIX}" \
|
||||
-DLLVM_ENABLE_LIBEDIT=OFF \
|
||||
-DLLVM_ENABLE_LIBXML2=OFF \
|
||||
-DLLVM_ENABLE_RTTI=ON \
|
||||
-DLLVM_ENABLE_TERMINFO=OFF \
|
||||
-DLLVM_INCLUDE_BENCHMARKS=OFF \
|
||||
-DLLVM_INCLUDE_DOCS=OFF \
|
||||
-DLLVM_INCLUDE_EXAMPLES=OFF \
|
||||
-DLLVM_INCLUDE_GO_TESTS=OFF \
|
||||
-DLLVM_INCLUDE_TESTS=OFF \
|
||||
-DLLVM_INCLUDE_UTILS=ON \
|
||||
-DLLVM_INSTALL_UTILS=ON \
|
||||
-DLLVM_UTILS_INSTALL_DIR=libexec/llvm \
|
||||
-DLLVM_BUILD_LLVM_DYLIB=OFF \
|
||||
-DLLVM_LINK_LLVM_DYLIB=OFF \
|
||||
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly \
|
||||
-DLLVM_ENABLE_FFI=ON \
|
||||
-DLLVM_ENABLE_Z3_SOLVER=OFF \
|
||||
-DLLVM_OPTIMIZED_TABLEGEN=ON \
|
||||
-DCMAKE_POLICY_DEFAULT_CMP0111=NEW \
|
||||
-DCOMPILER_RT_BUILD_BUILTINS=ON \
|
||||
-DCOMPILER_RT_BUILTINS_HIDE_SYMBOLS=OFF \
|
||||
-DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
|
||||
-DCOMPILER_RT_BUILD_CRT=OFF \
|
||||
-DCOMPILER_RT_BUILD_MEMPROF=OFF \
|
||||
-DCOMPILER_RT_BUILD_PROFILE=OFF \
|
||||
-DCOMPILER_RT_BUILD_SANITIZERS=OFF \
|
||||
-DCOMPILER_RT_BUILD_XRAY=OFF \
|
||||
-DCOMPILER_RT_BUILD_GWP_ASAN=OFF \
|
||||
-DCOMPILER_RT_BUILD_ORC=OFF \
|
||||
-DCOMPILER_RT_INCLUDE_TESTS=OFF \
|
||||
${CMAKE_ARGS} -GNinja ../llvm \
|
||||
&& ninja install . && \
|
||||
# build llvmlite
|
||||
cd ../../llvmlite && python setup.py bdist_wheel && \
|
||||
cd ../numba && \
|
||||
if ! grep '#include "dynamic_annotations.h"' numba/_dispatcher.cpp; then \
|
||||
sed -i '/#include "internal\/pycore_atomic.h"/i\#include "dynamic_annotations.h"' numba/_dispatcher.cpp; \
|
||||
fi && python setup.py bdist_wheel
|
||||
|
||||
# Build OpenCV from source for s390x
|
||||
FROM python-install AS opencv-builder
|
||||
WORKDIR /tmp
|
||||
ARG MAX_JOBS
|
||||
ARG OPENCV_VERSION=90
|
||||
ARG ENABLE_HEADLESS=1
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install numpy setuptools wheel scikit_build build && \
|
||||
git clone --recursive https://github.com/opencv/opencv-python.git -b ${OPENCV_VERSION} && \
|
||||
cd opencv-python && \
|
||||
python -m build --wheel --installer=uv --outdir /tmp/opencv-python/dist
|
||||
|
||||
## Todo(r3hankhan123): Remove guidance-builder stage once vLLM upgrades to new version of llguidance that fixes s390x issues. See https://github.com/guidance-ai/llguidance/issues/330
|
||||
FROM python-install AS guidance-builder
|
||||
WORKDIR /tmp
|
||||
ENV CARGO_HOME=/root/.cargo
|
||||
ENV RUSTUP_HOME=/root/.rustup
|
||||
ENV PATH="$CARGO_HOME/bin:$RUSTUP_HOME/bin:$PATH"
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=bind,from=rust,source=/root/.cargo,target=/root/.cargo,rw \
|
||||
--mount=type=bind,from=rust,source=/root/.rustup,target=/root/.rustup,rw \
|
||||
git clone https://github.com/guidance-ai/llguidance.git && \
|
||||
cd llguidance && \
|
||||
git checkout s390x-fix-v2 && \
|
||||
uv pip install maturin && \
|
||||
python -m maturin build --release --out dist --compatibility linux
|
||||
|
||||
# # Final build stage
|
||||
FROM python-install AS vllm-cpu
|
||||
ARG PYTHON_VERSION
|
||||
ARG PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/cpu"
|
||||
# Set correct library path for torch and numactl
|
||||
ENV LD_LIBRARY_PATH="/opt/vllm/lib64/python${PYTHON_VERSION}/site-packages/torch/lib:/usr/local/lib:/opt/rh/gcc-toolset-14/root/usr/lib64:$LD_LIBRARY_PATH"
|
||||
ENV C_INCLUDE_PATH="/usr/local/include:$C_INCLUDE_PATH"
|
||||
ENV UV_LINK_MODE=copy
|
||||
ENV CARGO_HOME=/root/.cargo
|
||||
ENV RUSTUP_HOME=/root/.rustup
|
||||
ENV GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1
|
||||
ENV PCP_DIR=/opt/rh/gcc-toolset-14/root
|
||||
ENV PKG_CONFIG_PATH="/opt/rh/gcc-toolset-14/root/usr/lib64/pkgconfig:/usr/local/lib/pkgconfig/"
|
||||
ENV PATH="${VIRTUAL_ENV:+${VIRTUAL_ENV}/bin}:/opt/rh/gcc-toolset-14/root/usr/bin:/usr/local/bin:$CARGO_HOME/bin:$RUSTUP_HOME/bin:$PATH"
|
||||
ENV PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL}
|
||||
ENV UV_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL}
|
||||
# Force pure Python protobuf to avoid s390x C++ extension crashes
|
||||
ENV PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
|
||||
COPY . /workspace/vllm
|
||||
WORKDIR /workspace/vllm
|
||||
|
||||
RUN --mount=type=bind,from=numa-build,src=/tmp/numactl-2.0.19,target=/numactl \
|
||||
make -C /numactl install
|
||||
|
||||
# Install dependencies, including PyTorch and Apache Arrow
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=bind,from=rust,source=/root/.cargo,target=/root/.cargo,rw \
|
||||
--mount=type=bind,from=rust,source=/root/.rustup,target=/root/.rustup,rw \
|
||||
--mount=type=bind,from=pyarrow,source=/tmp/arrow/python/dist,target=/tmp/arrow-wheels \
|
||||
--mount=type=bind,from=torch-vision,source=/tmp/vision/dist,target=/tmp/vision-wheels/ \
|
||||
--mount=type=bind,from=hf-xet-builder,source=/tmp/hf-xet/dist,target=/tmp/hf-xet-wheels/ \
|
||||
--mount=type=bind,from=numba-builder,source=/tmp/llvmlite/dist,target=/tmp/llvmlite-wheels/ \
|
||||
--mount=type=bind,from=numba-builder,source=/tmp/numba/dist,target=/tmp/numba-wheels/ \
|
||||
--mount=type=bind,from=opencv-builder,source=/tmp/opencv-python/dist,target=/tmp/opencv-wheels/ \
|
||||
--mount=type=bind,from=guidance-builder,source=/tmp/llguidance/dist,target=/tmp/guidance-wheels/ \
|
||||
ARROW_WHL_FILE=$(ls /tmp/arrow-wheels/*.whl) && \
|
||||
VISION_WHL_FILE=$(ls /tmp/vision-wheels/*.whl) && \
|
||||
HF_XET_WHL_FILE=$(ls /tmp/hf-xet-wheels/*.whl) && \
|
||||
LLVM_WHL_FILE=$(ls /tmp/llvmlite-wheels/*.whl) && \
|
||||
NUMBA_WHL_FILE=$(ls /tmp/numba-wheels/*.whl) && \
|
||||
OPENCV_WHL_FILE=$(ls /tmp/opencv-wheels/*.whl) && \
|
||||
GUIDANCE_WHL_FILE=$(ls /tmp/guidance-wheels/*.whl) && \
|
||||
uv pip install -v \
|
||||
$ARROW_WHL_FILE \
|
||||
$VISION_WHL_FILE \
|
||||
$HF_XET_WHL_FILE \
|
||||
$LLVM_WHL_FILE \
|
||||
$NUMBA_WHL_FILE \
|
||||
$OPENCV_WHL_FILE \
|
||||
$GUIDANCE_WHL_FILE \
|
||||
--torch-backend cpu \
|
||||
--index-strategy unsafe-best-match \
|
||||
-r requirements/build/cpu.txt \
|
||||
-r requirements/cpu.txt
|
||||
|
||||
|
||||
# Build and install vllm
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
VLLM_TARGET_DEVICE=cpu VLLM_CPU_MOE_PREPACK=0 python setup.py bdist_wheel && \
|
||||
uv pip install "$(echo dist/*.whl)[tensorizer]"
|
||||
|
||||
# Remove protobuf C++ extension that crashes on s390x
|
||||
RUN rm -rf /opt/vllm/lib64/python${PYTHON_VERSION}/site-packages/google/_upb/*.so \
|
||||
/opt/vllm/lib64/python${PYTHON_VERSION}/site-packages/google/protobuf/pyext/*.so 2>/dev/null || true
|
||||
|
||||
# setup non-root user for vllm
|
||||
RUN umask 002 && \
|
||||
/usr/sbin/useradd --uid 2000 --gid 0 vllm && \
|
||||
mkdir -p /home/vllm && \
|
||||
chmod g+rwx /home/vllm
|
||||
|
||||
COPY LICENSE /licenses/vllm.md
|
||||
COPY examples/*.jinja /app/data/template/
|
||||
|
||||
USER 2000
|
||||
WORKDIR /home/vllm
|
||||
|
||||
# Set the default entrypoint
|
||||
ENTRYPOINT ["vllm", "serve"]
|
||||
@@ -0,0 +1,36 @@
|
||||
ARG NIGHTLY_DATE="20250730"
|
||||
ARG BASE_IMAGE="us-central1-docker.pkg.dev/tpu-pytorch-releases/docker/xla:nightly_3.12_tpuvm_$NIGHTLY_DATE"
|
||||
|
||||
FROM $BASE_IMAGE
|
||||
WORKDIR /workspace/vllm
|
||||
|
||||
# Install some basic utilities
|
||||
RUN apt-get update && apt-get install -y \
|
||||
git \
|
||||
ffmpeg libsm6 libxext6 libgl1 && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Build vLLM.
|
||||
COPY . .
|
||||
ARG GIT_REPO_CHECK=0
|
||||
RUN --mount=type=bind,source=.git,target=.git \
|
||||
if [ "$GIT_REPO_CHECK" != 0 ]; then bash tools/check_repo.sh; fi
|
||||
|
||||
# Remove existing versions of dependencies
|
||||
# TODO: These packages will remain as dead weight in the Docker image layers.
|
||||
# We should find a way to build the image without uninstalling these.
|
||||
# Consider using a different base image.
|
||||
RUN pip uninstall -y torch torch_xla torchvision
|
||||
|
||||
ENV VLLM_TARGET_DEVICE="tpu"
|
||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||
--mount=type=bind,source=.git,target=.git \
|
||||
python3 -m pip install \
|
||||
-r requirements/tpu.txt
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/pip python3 -m pip install -e .
|
||||
|
||||
# install development dependencies (for testing)
|
||||
RUN --mount=type=cache,target=/root/.cache/pip python3 -m pip install -e tests/vllm_test_utils
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
@@ -0,0 +1,245 @@
|
||||
######################### RUST BUILD IMAGE #########################
|
||||
# Build the Rust frontend (`vllm-rs`) in a dedicated stage so the main image
|
||||
# doesn't need the rust toolchain or protoc. Runs in parallel with vllm-base.
|
||||
FROM ubuntu:22.04 AS rust-build
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update -y \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates curl git build-essential unzip python3 python3-pip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY tools/install_protoc.sh /tmp/install_protoc.sh
|
||||
RUN /tmp/install_protoc.sh && rm /tmp/install_protoc.sh
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
COPY requirements/build/rust.txt requirements/build/rust.txt
|
||||
RUN python3 -m pip install --no-cache-dir -r requirements/build/rust.txt
|
||||
|
||||
# Copy only the Rust build inputs; build_rust.sh publishes artifacts needed
|
||||
# by the wheel build stage.
|
||||
COPY rust rust
|
||||
COPY rust-toolchain.toml rust-toolchain.toml
|
||||
COPY tools/build_rust.py tools/build_rust.py
|
||||
COPY build_rust.sh build_rust.sh
|
||||
|
||||
# Cap cargo parallelism to avoid exhausting the CI host's open-file limit
|
||||
# (rustc spawns enough concurrent processes to hit RLIMIT_NOFILE otherwise).
|
||||
ENV CARGO_BUILD_JOBS=4
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cargo/registry,sharing=locked \
|
||||
--mount=type=cache,target=/root/.cargo/git,sharing=locked \
|
||||
bash build_rust.sh
|
||||
|
||||
FROM ubuntu:24.04 AS vllm-base
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
WORKDIR /workspace/
|
||||
|
||||
ARG PYTHON_VERSION=3.12
|
||||
ARG PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/xpu"
|
||||
|
||||
RUN apt-get update -y && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
curl \
|
||||
ffmpeg \
|
||||
git \
|
||||
gpg \
|
||||
libsndfile1 \
|
||||
libsm6 \
|
||||
libxext6 \
|
||||
libgl1 \
|
||||
lsb-release \
|
||||
libaio-dev \
|
||||
numactl \
|
||||
wget \
|
||||
vim \
|
||||
ca-certificates \
|
||||
python3.12 \
|
||||
python3.12-dev \
|
||||
python3-pip && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Add oneAPI repo, pin oneAPI to 2025.3, then install pinned packages in one layer.
|
||||
RUN wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | gpg --dearmor | tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null && \
|
||||
echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | tee /etc/apt/sources.list.d/oneAPI.list && \
|
||||
printf '%s\n' \
|
||||
'Package: intel-oneapi-* intel-deep-learning-essentials* intel-pti*' \
|
||||
'Pin: version 2025.3*' \
|
||||
'Pin-Priority: 1001' \
|
||||
> /etc/apt/preferences.d/oneapi-2025.3.pref && \
|
||||
apt-get update -y && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
intel-oneapi-compiler-dpcpp-cpp-2025.3 \
|
||||
intel-oneapi-mkl-devel-2025.3 \
|
||||
intel-oneapi-dnnl-devel-2025.3 && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install UMD
|
||||
RUN mkdir neo && \
|
||||
cd neo && \
|
||||
wget https://github.com/intel/intel-graphics-compiler/releases/download/v2.34.4/intel-igc-core-2_2.34.4+21428_amd64.deb && \
|
||||
wget https://github.com/intel/intel-graphics-compiler/releases/download/v2.34.4/intel-igc-opencl-2_2.34.4+21428_amd64.deb && \
|
||||
wget https://github.com/intel/compute-runtime/releases/download/26.18.38308.1/intel-ocloc_26.18.38308.1-0_amd64.deb && \
|
||||
wget https://github.com/intel/compute-runtime/releases/download/26.18.38308.1/intel-opencl-icd_26.18.38308.1-0_amd64.deb && \
|
||||
wget https://github.com/intel/compute-runtime/releases/download/26.18.38308.1/libigdgmm12_22.10.0_amd64.deb && \
|
||||
wget https://github.com/intel/compute-runtime/releases/download/26.18.38308.1/libze-intel-gpu1_26.18.38308.1-0_amd64.deb && \
|
||||
wget https://github.com/oneapi-src/level-zero/releases/download/v1.28.2/level-zero_1.28.2+u24.04_amd64.deb && \
|
||||
wget https://github.com/oneapi-src/level-zero/releases/download/v1.28.2/level-zero-devel_1.28.2+u24.04_amd64.deb && \
|
||||
dpkg -i *.deb && \
|
||||
cd .. && \
|
||||
rm -rf neo
|
||||
|
||||
ENV PATH="/root/.local/bin:$PATH"
|
||||
ENV VIRTUAL_ENV="/opt/venv"
|
||||
ENV UV_PYTHON_INSTALL_DIR=/opt/uv/python
|
||||
RUN curl -LsSf https://astral.sh/uv/install.sh | sh \
|
||||
&& uv venv --python ${PYTHON_VERSION} --seed ${VIRTUAL_ENV}
|
||||
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
|
||||
|
||||
# This oneccl contains the BMG support which is not the case for default version of oneapi 2025.3.
|
||||
ARG ONECCL_INSTALLER="intel-oneccl-2021.15.9.14_offline.sh"
|
||||
RUN wget "https://github.com/uxlfoundation/oneCCL/releases/download/2021.15.9/${ONECCL_INSTALLER}" && \
|
||||
bash "${ONECCL_INSTALLER}" -a --silent --eula accept && \
|
||||
rm "${ONECCL_INSTALLER}" && \
|
||||
echo "source /opt/intel/oneapi/setvars.sh --force" >> /root/.bashrc && \
|
||||
echo "source /opt/intel/oneapi/ccl/2021.15/env/vars.sh --force" >> /root/.bashrc && \
|
||||
rm -f /opt/intel/oneapi/ccl/latest && \
|
||||
ln -s /opt/intel/oneapi/ccl/2021.15 /opt/intel/oneapi/ccl/latest && \
|
||||
printf '%s\n' \
|
||||
'/opt/intel/oneapi/ccl/2021.15/lib' \
|
||||
'/opt/intel/oneapi/mpi/2021.15/lib' \
|
||||
'/opt/intel/oneapi/compiler/2025.3/lib' \
|
||||
> /etc/ld.so.conf.d/oneapi-ccl.conf && \
|
||||
ldconfig
|
||||
|
||||
SHELL ["bash", "-c"]
|
||||
CMD ["bash", "-c", "source /root/.bashrc && exec bash"]
|
||||
|
||||
WORKDIR /workspace/vllm
|
||||
|
||||
ENV UV_HTTP_TIMEOUT=500
|
||||
|
||||
# Configure package index for XPU
|
||||
ENV PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL}
|
||||
ENV UV_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL}
|
||||
ENV UV_INDEX_STRATEGY="unsafe-best-match"
|
||||
ENV UV_LINK_MODE="copy"
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=bind,src=requirements/common.txt,target=/workspace/vllm/requirements/common.txt \
|
||||
--mount=type=bind,src=requirements/xpu.txt,target=/workspace/vllm/requirements/xpu.txt \
|
||||
uv pip install --upgrade pip
|
||||
|
||||
|
||||
|
||||
ENV LD_LIBRARY_PATH=/opt/intel/oneapi/ccl/2021.15/lib:/opt/intel/oneapi/mpi/2021.15/lib:/opt/intel/oneapi/compiler/2025.3/lib:/usr/local/lib
|
||||
CMD ["/bin/bash"]
|
||||
|
||||
######################### UCX + NIXL BUILD STAGE #########################
|
||||
# Build UCX and NIXL in a dedicated stage so compiler/autotools layers are
|
||||
# never included in the final runtime image (mirrors ROCm's build_rixl stage).
|
||||
FROM vllm-base AS ucx-nixl-build
|
||||
|
||||
ARG UCX_VERSION=v1.21.0-rc2
|
||||
ARG NIXL_VERSION=v1.2.0
|
||||
|
||||
# Build-time only: compiler, autotools, and verbs dev headers
|
||||
RUN apt-get update -y && apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
autoconf \
|
||||
automake \
|
||||
libtool \
|
||||
pkg-config \
|
||||
libibverbs-dev \
|
||||
librdmacm-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Build UCX and produce a NIXL wheel so the final image needs no compiler.
|
||||
# patchelf (installed via uv) is used by the NIXL wheel build to rewrite
|
||||
# RPATH entries, making the wheel portable across stages.
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
git clone --depth 1 --branch "${UCX_VERSION}" https://github.com/openucx/ucx /tmp/ucx_source && \
|
||||
cd /tmp/ucx_source && \
|
||||
bash autogen.sh && \
|
||||
./configure --prefix=/tmp/ucx_install --with-ze=yes --enable-examples --enable-mt && \
|
||||
make CFLAGS="-Wno-error=incompatible-pointer-types" -j"$(nproc)" && make install && \
|
||||
git clone --depth 1 --branch "${NIXL_VERSION}" https://github.com/ai-dynamo/nixl /tmp/nixl_source && \
|
||||
cd /tmp/nixl_source && \
|
||||
uv pip install --upgrade meson pybind11 patchelf && \
|
||||
uv pip install -r requirements.txt && \
|
||||
PKG_CONFIG_PATH=/tmp/ucx_install/lib/pkgconfig \
|
||||
LD_LIBRARY_PATH=/tmp/ucx_install/lib \
|
||||
python -m pip wheel --no-deps . -w /tmp/nixl_wheels/ && \
|
||||
find /tmp/ucx_install -type f \( -name '*.a' -o -name '*.la' \) -delete && \
|
||||
rm -rf /tmp/ucx_install/{include,share,etc,bin} /tmp/ucx_install/lib/cmake \
|
||||
/tmp/ucx_source /tmp/nixl_source
|
||||
|
||||
FROM vllm-base AS vllm-openai
|
||||
|
||||
ARG NIXL_VERSION=v1.2.0
|
||||
|
||||
# Copy compiled UCX runtime libraries and the pre-built NIXL wheel.
|
||||
# No compiler or autotools are installed in this stage.
|
||||
COPY --from=ucx-nixl-build /tmp/ucx_install /tmp/ucx_install
|
||||
COPY --from=ucx-nixl-build /tmp/nixl_wheels /tmp/nixl_wheels
|
||||
|
||||
ENV LD_LIBRARY_PATH=/tmp/ucx_install/lib:${LD_LIBRARY_PATH}
|
||||
|
||||
# Install RDMA runtime libraries (no build tools) and the pre-built NIXL wheel.
|
||||
# Do not uninstall/reinstall large Python packages here to avoid extra layer
|
||||
# churn; final package resolution remains in the later app install step.
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
apt-get update -y && apt-get install -y --no-install-recommends \
|
||||
rdma-core \
|
||||
libibverbs1 \
|
||||
librdmacm1 \
|
||||
libibumad3 \
|
||||
libibmad5 \
|
||||
libmlx5-1 \
|
||||
libmlx4-1 \
|
||||
ibverbs-providers \
|
||||
librdmacm1t64 \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& uv pip install --no-deps /tmp/nixl_wheels/nixl*.whl \
|
||||
&& uv pip install nixl==${NIXL_VERSION} && uv pip uninstall nixl-cu13 \
|
||||
&& rm -rf /tmp/nixl_wheels
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=bind,src=requirements/common.txt,target=/workspace/vllm/requirements/common.txt \
|
||||
--mount=type=bind,src=requirements/xpu.txt,target=/workspace/vllm/requirements/xpu.txt \
|
||||
--mount=type=bind,src=requirements/test/xpu.txt,target=/workspace/vllm/requirements/test/xpu.txt \
|
||||
uv pip install grpcio-tools protobuf nanobind && \
|
||||
uv pip install -r /workspace/vllm/requirements/xpu.txt && \
|
||||
uv pip install --no-build-isolation -r /workspace/vllm/requirements/test/xpu.txt && \
|
||||
uv pip uninstall triton triton-xpu && \
|
||||
uv pip install triton-xpu==3.7.1 && \
|
||||
uv pip uninstall oneccl oneccl-devel
|
||||
|
||||
# Keep source-dependent layers near the end so frequent code-only changes
|
||||
# don't invalidate heavy dependency and UCX/NIXL layers.
|
||||
COPY . .
|
||||
|
||||
# Drop the pre-built Rust artifacts into the source tree. setup.py detects
|
||||
# them and ships them as-is, skipping the local Rust build.
|
||||
COPY --from=rust-build /workspace/vllm/vllm-rs vllm/vllm-rs
|
||||
COPY --from=rust-build /workspace/vllm/_rust_*.so vllm/
|
||||
|
||||
ARG GIT_REPO_CHECK=0
|
||||
RUN --mount=type=bind,source=.git,target=.git \
|
||||
if [ "$GIT_REPO_CHECK" != 0 ]; then bash tools/check_repo.sh; fi
|
||||
|
||||
ENV VLLM_TARGET_DEVICE=xpu
|
||||
ENV VLLM_WORKER_MULTIPROC_METHOD=spawn
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=bind,source=.git,target=.git \
|
||||
uv pip install --no-build-isolation --no-deps .
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv pip install -e tests/vllm_test_utils
|
||||
|
||||
ENTRYPOINT ["vllm", "serve"]
|
||||
@@ -0,0 +1,385 @@
|
||||
# ci-rocm.hcl - CI-specific configuration for vLLM ROCm Docker builds
|
||||
#
|
||||
# This file lives in the vLLM repo at docker/ci-rocm.hcl so ROCm Docker
|
||||
# build mechanics can evolve with Dockerfile.rocm and docker-bake-rocm.hcl.
|
||||
# Used with: docker buildx bake -f docker/docker-bake-rocm.hcl -f docker/ci-rocm.hcl test-rocm-ci
|
||||
#
|
||||
# Registry cache: Docker Hub (rocm/vllm-ci-cache) is used exclusively.
|
||||
# AMD build agents already have Docker Hub credentials (they push the test
|
||||
# image to rocm/vllm-ci), so no additional credential setup is required.
|
||||
# ROCm CI uses Docker Hub for BuildKit layer cache by default. A separate
|
||||
# compiler cache can be enabled with USE_SCCACHE=1 when AMD provides a shared
|
||||
# S3-compatible cache endpoint.
|
||||
|
||||
# CI metadata
|
||||
|
||||
variable "BUILDKITE_COMMIT" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "BUILDKITE_BUILD_NUMBER" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "BUILDKITE_BUILD_ID" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "PARENT_COMMIT" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# Merge-base of HEAD with main - provides a more stable cache fallback than
|
||||
# parent commit for long-lived PRs. Mirrors the VLLM_MERGE_BASE_COMMIT
|
||||
# pattern used in the shared ci.hcl file. Auto-computed by ci-bake-rocm.sh
|
||||
# when unset.
|
||||
variable "VLLM_MERGE_BASE_COMMIT" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# Bridge to vLLM's COMMIT variable for OCI labels
|
||||
variable "COMMIT" {
|
||||
default = BUILDKITE_COMMIT
|
||||
}
|
||||
|
||||
# Image tags (set by CI)
|
||||
|
||||
variable "IMAGE_TAG" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "IMAGE_TAG_LATEST" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# ROCm-specific GPU architecture targets
|
||||
|
||||
variable "PYTORCH_ROCM_ARCH" {
|
||||
default = "gfx90a;gfx942;gfx950"
|
||||
}
|
||||
|
||||
# Pre-built CI base image (Tier 1). Per-PR builds pull this instead of
|
||||
# rebuilding RIXL/DeepEP/torchcodec from scratch. The ci_base stage in
|
||||
# Dockerfile.rocm inherits from base, so CI_BASE_IMAGE only affects the test
|
||||
# stage and is irrelevant when building --target ci_base itself.
|
||||
variable "CI_BASE_IMAGE" {
|
||||
default = "rocm/vllm-dev:ci_base"
|
||||
}
|
||||
|
||||
# Leave CI_MAX_JOBS empty so the Dockerfile falls back to $(nproc) and uses
|
||||
# the full builder parallelism. Operators can still override this per build.
|
||||
variable "CI_MAX_JOBS" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# Upstream dependency commit pins -- extracted from Dockerfile.rocm by
|
||||
# ci-bake-rocm.sh at build time. Empty defaults are safe: the cache
|
||||
# functions produce no entries when the variable is empty.
|
||||
variable "RIXL_BRANCH" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "UCX_BRANCH" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "ROCSHMEM_BRANCH" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "DEEPEP_BRANCH" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "RIXL_CACHE_KEY" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "ROCSHMEM_CACHE_KEY" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "DEEPEP_CACHE_KEY" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# Docker Hub registry cache for AMD builds.
|
||||
#
|
||||
# A separate repo (rocm/vllm-ci-cache) is used for BuildKit layer cache.
|
||||
# Final-image cache exports use mode=min to reduce the volume of data pushed.
|
||||
# Source-scoped csrc cache exports default to mode=max so fresh workers can
|
||||
# recover more of the native build graph when ROCm extension inputs change.
|
||||
# NOTE: mode=min still includes all layers referenced by the final image
|
||||
# manifest, including inherited base layers (~7.25GB ROCm runtime).
|
||||
# Docker Hub auto-creates the repo on first push.
|
||||
#
|
||||
# Final-image cache stays commit-scoped. Branch-to-branch reuse for the test
|
||||
# image comes from importing the parent and merge-base commit cache refs.
|
||||
#
|
||||
# The source-scoped native cache is exported both per-commit and per-branch so
|
||||
# ROCm extension rebuilds are shareable within the same commit reruns and across
|
||||
# consecutive commits on the same branch without depending on a single global
|
||||
# latest tag.
|
||||
|
||||
variable "DOCKERHUB_CACHE_REPO" {
|
||||
default = "rocm/vllm-ci-cache"
|
||||
}
|
||||
|
||||
variable "DOCKERHUB_CACHE_TO" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "ROCM_CACHE_BRANCH_TAG" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "ROCM_CACHE_UPSTREAM_BRANCH_TAG" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "ROCM_CSRC_CACHE_TO_MODE" {
|
||||
default = "max"
|
||||
}
|
||||
|
||||
variable "ROCM_FINAL_CACHE_TO_MODE" {
|
||||
default = "min"
|
||||
}
|
||||
|
||||
# Functions
|
||||
|
||||
function "get_cache_from_rocm" {
|
||||
params = []
|
||||
result = compact([
|
||||
# Exact commit hit - fastest cache on re-runs of the same commit
|
||||
BUILDKITE_COMMIT != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rocm-${BUILDKITE_COMMIT}" : "",
|
||||
# Parent commit - useful cache for incremental changes
|
||||
PARENT_COMMIT != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rocm-${PARENT_COMMIT}" : "",
|
||||
# Merge-base with main - stable fallback for long-lived or rebased PRs;
|
||||
# maps to a real main-branch commit whose cache layers are likely warm
|
||||
VLLM_MERGE_BASE_COMMIT != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rocm-${VLLM_MERGE_BASE_COMMIT}" : "",
|
||||
# Import the source-scoped native build cache as well so builds whose
|
||||
# Python/package layers changed can still reuse compiled ROCm objects.
|
||||
BUILDKITE_COMMIT != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:csrc-rocm-${BUILDKITE_COMMIT}" : "",
|
||||
PARENT_COMMIT != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:csrc-rocm-${PARENT_COMMIT}" : "",
|
||||
VLLM_MERGE_BASE_COMMIT != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:csrc-rocm-${VLLM_MERGE_BASE_COMMIT}" : "",
|
||||
ROCM_CACHE_BRANCH_TAG != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:csrc-rocm-branch-${ROCM_CACHE_BRANCH_TAG}" : "",
|
||||
ROCM_CACHE_UPSTREAM_BRANCH_TAG != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:csrc-rocm-branch-${ROCM_CACHE_UPSTREAM_BRANCH_TAG}" : "",
|
||||
# Branch-scoped full image cache - fallback when parent-commit cache is evicted
|
||||
ROCM_CACHE_BRANCH_TAG != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rocm-branch-${ROCM_CACHE_BRANCH_TAG}" : "",
|
||||
ROCM_CACHE_UPSTREAM_BRANCH_TAG != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rocm-branch-${ROCM_CACHE_UPSTREAM_BRANCH_TAG}" : "",
|
||||
])
|
||||
}
|
||||
|
||||
function "get_cache_to_rocm" {
|
||||
params = []
|
||||
result = compact([
|
||||
# Commit-scoped cache for exact re-runs.
|
||||
BUILDKITE_COMMIT != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rocm-${BUILDKITE_COMMIT},mode=${ROCM_FINAL_CACHE_TO_MODE}" : "",
|
||||
# Branch-scoped cache so later commits on the same branch can reuse the full
|
||||
# image layers when the parent-commit cache is evicted. Unlike the old
|
||||
# rocm-latest tag (which caused duplicate exporter 400s), this is per-branch.
|
||||
ROCM_CACHE_BRANCH_TAG != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rocm-branch-${ROCM_CACHE_BRANCH_TAG},mode=${ROCM_FINAL_CACHE_TO_MODE}" : "",
|
||||
])
|
||||
}
|
||||
|
||||
function "get_cache_from_rocm_csrc" {
|
||||
params = []
|
||||
result = compact([
|
||||
BUILDKITE_COMMIT != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:csrc-rocm-${BUILDKITE_COMMIT}" : "",
|
||||
PARENT_COMMIT != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:csrc-rocm-${PARENT_COMMIT}" : "",
|
||||
VLLM_MERGE_BASE_COMMIT != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:csrc-rocm-${VLLM_MERGE_BASE_COMMIT}" : "",
|
||||
ROCM_CACHE_BRANCH_TAG != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:csrc-rocm-branch-${ROCM_CACHE_BRANCH_TAG}" : "",
|
||||
ROCM_CACHE_UPSTREAM_BRANCH_TAG != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:csrc-rocm-branch-${ROCM_CACHE_UPSTREAM_BRANCH_TAG}" : "",
|
||||
])
|
||||
}
|
||||
|
||||
function "get_cache_to_rocm_csrc" {
|
||||
params = []
|
||||
result = compact([
|
||||
# Export the exact-commit native cache for same-commit reruns.
|
||||
BUILDKITE_COMMIT != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:csrc-rocm-${BUILDKITE_COMMIT},mode=${ROCM_CSRC_CACHE_TO_MODE}" : "",
|
||||
# Export the branch-scoped native cache so later commits on the same branch
|
||||
# can reuse compiled ROCm objects even when the exact parent cache is absent.
|
||||
ROCM_CACHE_BRANCH_TAG != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:csrc-rocm-branch-${ROCM_CACHE_BRANCH_TAG},mode=${ROCM_CSRC_CACHE_TO_MODE}" : "",
|
||||
])
|
||||
}
|
||||
|
||||
# Cache functions for upstream dependency stages (RIXL/UCX, ROCShmem, DeepEP).
|
||||
# These stages are pinned to specific upstream commit hashes, so cache keys use
|
||||
# those hashes rather than the Buildkite commit. This means the cache persists
|
||||
# across all vLLM commits as long as the upstream dependency pins don't change.
|
||||
|
||||
function "get_cache_from_rocm_deps" {
|
||||
params = []
|
||||
result = compact([
|
||||
RIXL_CACHE_KEY != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rixl-rocm-${RIXL_CACHE_KEY}" : (RIXL_BRANCH != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rixl-rocm-${RIXL_BRANCH}-ucx-${UCX_BRANCH}" : ""),
|
||||
ROCSHMEM_CACHE_KEY != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rocshmem-rocm-${ROCSHMEM_CACHE_KEY}" : (ROCSHMEM_BRANCH != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rocshmem-rocm-${ROCSHMEM_BRANCH}" : ""),
|
||||
DEEPEP_CACHE_KEY != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:deepep-rocm-${DEEPEP_CACHE_KEY}" : (DEEPEP_BRANCH != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:deepep-rocm-${DEEPEP_BRANCH}-rocshmem-${ROCSHMEM_BRANCH}" : ""),
|
||||
])
|
||||
}
|
||||
|
||||
function "get_cache_to_rocm_rixl" {
|
||||
params = []
|
||||
result = compact([
|
||||
RIXL_CACHE_KEY != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rixl-rocm-${RIXL_CACHE_KEY},mode=min" : (RIXL_BRANCH != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rixl-rocm-${RIXL_BRANCH}-ucx-${UCX_BRANCH},mode=min" : ""),
|
||||
])
|
||||
}
|
||||
|
||||
function "get_cache_to_rocm_rocshmem" {
|
||||
params = []
|
||||
result = compact([
|
||||
ROCSHMEM_CACHE_KEY != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rocshmem-rocm-${ROCSHMEM_CACHE_KEY},mode=min" : (ROCSHMEM_BRANCH != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:rocshmem-rocm-${ROCSHMEM_BRANCH},mode=min" : ""),
|
||||
])
|
||||
}
|
||||
|
||||
function "get_cache_to_rocm_deepep" {
|
||||
params = []
|
||||
result = compact([
|
||||
DEEPEP_CACHE_KEY != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:deepep-rocm-${DEEPEP_CACHE_KEY},mode=min" : (DEEPEP_BRANCH != "" ? "type=registry,ref=${DOCKERHUB_CACHE_REPO}:deepep-rocm-${DEEPEP_BRANCH}-rocshmem-${ROCSHMEM_BRANCH},mode=min" : ""),
|
||||
])
|
||||
}
|
||||
|
||||
# CI targets
|
||||
|
||||
target "_ci-rocm" {
|
||||
annotations = [
|
||||
"manifest:vllm.buildkite.build_number=${BUILDKITE_BUILD_NUMBER}",
|
||||
"manifest:vllm.buildkite.build_id=${BUILDKITE_BUILD_ID}",
|
||||
]
|
||||
args = {
|
||||
ARG_PYTORCH_ROCM_ARCH = PYTORCH_ROCM_ARCH
|
||||
CI_BASE_IMAGE = CI_BASE_IMAGE
|
||||
max_jobs = CI_MAX_JOBS
|
||||
}
|
||||
}
|
||||
|
||||
target "test-rocm-ci" {
|
||||
inherits = ["_common-rocm", "_ci-rocm", "_labels"]
|
||||
target = "test"
|
||||
cache-from = get_cache_from_rocm()
|
||||
cache-to = get_cache_to_rocm()
|
||||
tags = compact([
|
||||
IMAGE_TAG,
|
||||
IMAGE_TAG_LATEST,
|
||||
])
|
||||
output = ["type=registry"]
|
||||
}
|
||||
|
||||
# Cache-only target for the source-scoped ROCm native build stage.
|
||||
# This persists the csrc-build stage in the registry cache even though the
|
||||
# final test image only consumes it indirectly while packaging the wheel.
|
||||
target "csrc-rocm-ci" {
|
||||
inherits = ["_common-rocm", "_ci-rocm"]
|
||||
target = "csrc-build"
|
||||
cache-from = get_cache_from_rocm_csrc()
|
||||
cache-to = get_cache_to_rocm_csrc()
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
# Keep wheel export on the same CI graph as the test image build so the
|
||||
# shared build_vllm/export_vllm stages resolve identically within one bake
|
||||
# invocation. Without this, export-wheel-rocm uses the plain local target
|
||||
# args while test-rocm-ci uses CI-only args, which can lead to separate
|
||||
# cache lineages and inconsistent export_vllm results.
|
||||
target "export-wheel-rocm" {
|
||||
inherits = ["_common-rocm", "_ci-rocm"]
|
||||
target = "export_vllm"
|
||||
cache-from = get_cache_from_rocm()
|
||||
cache-to = get_cache_to_rocm()
|
||||
output = ["type=local,dest=./wheel-export"]
|
||||
}
|
||||
|
||||
# Artifact-only vLLM build. GPU test jobs consume this artifact on top of
|
||||
# ci_base, avoiding a per-commit multi-GB image push/pull.
|
||||
group "test-rocm-ci-with-artifacts" {
|
||||
targets = ["csrc-rocm-ci", "export-wheel-rocm"]
|
||||
}
|
||||
|
||||
# Full test image + wheel export. Kept for fallback/debugging when a pushed
|
||||
# per-commit image is useful.
|
||||
group "test-rocm-ci-with-wheel" {
|
||||
targets = ["csrc-rocm-ci", "test-rocm-ci", "export-wheel-rocm"]
|
||||
}
|
||||
|
||||
# Image tags for the ci_base build. ci-bake-rocm.sh rewrites CI_BASE_IMAGE_TAG
|
||||
# to the primary tag for this build. Builds always publish a content-scoped tag
|
||||
# when the ci_base content hash is available. Builds with BUILDKITE_COMMIT also
|
||||
# publish a commit-scoped tag, either as the primary tag or an additional alias.
|
||||
# NIGHTLY=1 builds on the stable branch can additionally set
|
||||
# CI_BASE_IMAGE_TAG_STABLE to refresh rocm/vllm-dev:ci_base.
|
||||
variable "CI_BASE_IMAGE_TAG" {
|
||||
default = "rocm/vllm-dev:ci_base"
|
||||
}
|
||||
|
||||
# Supplemental tags only. ci-bake-rocm.sh leaves these empty when the same ref
|
||||
# is already the primary CI_BASE_IMAGE_TAG.
|
||||
variable "CI_BASE_IMAGE_TAG_COMMIT_EXTRA" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "CI_BASE_IMAGE_TAG_CONTENT_EXTRA" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "CI_BASE_IMAGE_TAG_STABLE" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# Cache-only targets for upstream dependency stages. These persist each stage
|
||||
# in the registry cache keyed by its upstream commit hash. When ci_base rebuilds
|
||||
# (e.g., requirements change), these stages are cache hits if their upstream
|
||||
# pins haven't changed -- saving ~35min of compilation.
|
||||
target "rixl-rocm-ci" {
|
||||
inherits = ["_common-rocm", "_ci-rocm"]
|
||||
target = "build_rixl"
|
||||
cache-from = get_cache_from_rocm_deps()
|
||||
cache-to = get_cache_to_rocm_rixl()
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "rocshmem-rocm-ci" {
|
||||
inherits = ["_common-rocm", "_ci-rocm"]
|
||||
target = "build_rocshmem"
|
||||
cache-from = get_cache_from_rocm_deps()
|
||||
cache-to = get_cache_to_rocm_rocshmem()
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "deepep-rocm-ci" {
|
||||
inherits = ["_common-rocm", "_ci-rocm"]
|
||||
target = "build_deepep"
|
||||
cache-from = get_cache_from_rocm_deps()
|
||||
cache-to = get_cache_to_rocm_deepep()
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
# Builds only the ci_base stage (RIXL, DeepEP, torchcodec, etc.)
|
||||
# Invoked by the ensure-ci-base step when the content hash of ci_base-affecting
|
||||
# files drifts from the remote image label. Per-PR builds then pull the result
|
||||
# as CI_BASE_IMAGE instead of rebuilding those slow layers on every commit.
|
||||
# Uses inline cache metadata on the ci_base image itself instead of exporting a
|
||||
# separate registry cache artifact.
|
||||
target "ci-base-rocm-ci" {
|
||||
inherits = ["_common-rocm", "_ci-rocm", "_labels"]
|
||||
target = "ci_base"
|
||||
cache-from = concat(
|
||||
compact([
|
||||
CI_BASE_IMAGE_TAG != "" ? "type=registry,ref=${CI_BASE_IMAGE_TAG}" : "",
|
||||
CI_BASE_IMAGE_TAG_COMMIT_EXTRA != "" ? "type=registry,ref=${CI_BASE_IMAGE_TAG_COMMIT_EXTRA}" : "",
|
||||
CI_BASE_IMAGE_TAG_CONTENT_EXTRA != "" ? "type=registry,ref=${CI_BASE_IMAGE_TAG_CONTENT_EXTRA}" : "",
|
||||
CI_BASE_IMAGE_TAG_STABLE != "" ? "type=registry,ref=${CI_BASE_IMAGE_TAG_STABLE}" : "",
|
||||
]),
|
||||
# Import upstream dependency caches so RIXL/ROCShmem/DeepEP stages
|
||||
# are cache hits even when ci_base itself needs rebuilding.
|
||||
get_cache_from_rocm_deps(),
|
||||
)
|
||||
cache-to = ["type=inline"]
|
||||
tags = compact([CI_BASE_IMAGE_TAG, CI_BASE_IMAGE_TAG_COMMIT_EXTRA, CI_BASE_IMAGE_TAG_CONTENT_EXTRA, CI_BASE_IMAGE_TAG_STABLE])
|
||||
output = ["type=registry"]
|
||||
}
|
||||
|
||||
# Group for ci_base builds -- exports dependency stage caches alongside the
|
||||
# ci_base image so future rebuilds can reuse them independently.
|
||||
group "ci-base-rocm-ci-with-deps" {
|
||||
targets = ["rixl-rocm-ci", "rocshmem-rocm-ci", "deepep-rocm-ci", "ci-base-rocm-ci"]
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
# docker-bake-rocm.hcl - vLLM ROCm Docker build configuration
|
||||
#
|
||||
# This file lives in the vLLM repo at docker/docker-bake-rocm.hcl
|
||||
# Equivalent of docker-bake.hcl for ROCm builds.
|
||||
#
|
||||
# Usage:
|
||||
# docker buildx bake -f docker/docker-bake-rocm.hcl # Build test (default)
|
||||
# docker buildx bake -f docker/docker-bake-rocm.hcl final-rocm # Build final image
|
||||
# docker buildx bake -f docker/docker-bake-rocm.hcl --print # Show resolved config
|
||||
#
|
||||
# CI usage (with the vLLM-owned CI overlay):
|
||||
# docker buildx bake -f docker/docker-bake-rocm.hcl -f docker/ci-rocm.hcl test-rocm-ci
|
||||
|
||||
variable "MAX_JOBS" {
|
||||
# Empty string lets the Dockerfile fall back to $(nproc) via
|
||||
# MAX_JOBS="${MAX_JOBS:-$(nproc)}" in each RUN step, which uses all
|
||||
# available cores on whatever machine the build runs on.
|
||||
# Override with --set '*.args.max_jobs=8' for local builds on small machines.
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "PYTORCH_ROCM_ARCH" {
|
||||
default = "gfx90a;gfx942;gfx950"
|
||||
}
|
||||
|
||||
variable "COMMIT" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# Content hash of ci_base-affecting files. Computed by ci-bake-rocm.sh and
|
||||
# embedded as a label so future builds can compare without rebuilding.
|
||||
variable "CI_BASE_CONTENT_HASH" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# REMOTE_VLLM=0: use local source via Docker build context (ONBUILD COPY ./ vllm/)
|
||||
# REMOTE_VLLM=1: clone from GitHub at VLLM_BRANCH (standalone builds without local source)
|
||||
variable "REMOTE_VLLM" {
|
||||
default = "0"
|
||||
}
|
||||
|
||||
variable "VLLM_BRANCH" {
|
||||
default = "main"
|
||||
}
|
||||
|
||||
# CI_BASE_IMAGE: pre-built ci_base image for per-PR test builds.
|
||||
# Defaults to the local "ci_base" stage for standalone/local builds.
|
||||
# CI overrides this to "rocm/vllm-dev:ci_base" via environment variable.
|
||||
variable "CI_BASE_IMAGE" {
|
||||
default = "rocm/vllm-dev:ci_base"
|
||||
}
|
||||
|
||||
# Upstream dependency commit pins. Plain local bake builds use the Dockerfile
|
||||
# ARG defaults. ci-bake-rocm.sh resolves those defaults (plus any env
|
||||
# overrides) and writes a small HCL override before invoking CI targets.
|
||||
variable "RIXL_BRANCH" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "UCX_BRANCH" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "ROCSHMEM_BRANCH" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "DEEPEP_BRANCH" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
group "default" {
|
||||
targets = ["test-rocm"]
|
||||
}
|
||||
|
||||
target "_common-rocm" {
|
||||
dockerfile = "docker/Dockerfile.rocm"
|
||||
context = "."
|
||||
args = {
|
||||
max_jobs = MAX_JOBS
|
||||
ARG_PYTORCH_ROCM_ARCH = PYTORCH_ROCM_ARCH
|
||||
REMOTE_VLLM = REMOTE_VLLM
|
||||
VLLM_BRANCH = VLLM_BRANCH
|
||||
CI_BASE_IMAGE = CI_BASE_IMAGE
|
||||
}
|
||||
}
|
||||
|
||||
target "_labels" {
|
||||
labels = {
|
||||
"org.opencontainers.image.source" = "https://github.com/vllm-project/vllm"
|
||||
"org.opencontainers.image.vendor" = "vLLM"
|
||||
"org.opencontainers.image.title" = "vLLM ROCm"
|
||||
"org.opencontainers.image.description" = "vLLM: A high-throughput and memory-efficient inference and serving engine for LLMs (ROCm)"
|
||||
"org.opencontainers.image.licenses" = "Apache-2.0"
|
||||
"org.opencontainers.image.revision" = COMMIT
|
||||
}
|
||||
annotations = [
|
||||
"manifest:org.opencontainers.image.revision=${COMMIT}",
|
||||
]
|
||||
}
|
||||
|
||||
target "test-rocm" {
|
||||
inherits = ["_common-rocm", "_labels"]
|
||||
target = "test"
|
||||
tags = ["rocm/vllm:test"]
|
||||
output = ["type=docker"]
|
||||
}
|
||||
|
||||
# CI base image target - builds only the ci_base stage (RIXL, DeepEP,
|
||||
# torchcodec, requirements, etc.). Used by the weekly scheduled build and
|
||||
# the auto-rebuild trigger when requirements change in a PR.
|
||||
target "ci-base-rocm" {
|
||||
inherits = ["_common-rocm", "_labels"]
|
||||
target = "ci_base"
|
||||
labels = {
|
||||
"vllm.ci_base.content_hash" = CI_BASE_CONTENT_HASH
|
||||
}
|
||||
tags = ["rocm/vllm-dev:ci_base"]
|
||||
output = ["type=docker"]
|
||||
}
|
||||
|
||||
# Wheel export target - extracts the built vLLM wheel + test workspace
|
||||
# to local disk. Used by CI to upload the wheel as a Buildkite artifact
|
||||
# so test jobs can assemble images locally from ci_base + wheel instead
|
||||
# of pulling the full large image from Docker Hub.
|
||||
#
|
||||
# Usage:
|
||||
# docker buildx bake -f docker/docker-bake-rocm.hcl export-wheel-rocm
|
||||
# # Creates ./wheel-export/*.whl, ./wheel-export/requirements/, etc.
|
||||
#
|
||||
# After a full bake build, BuildKit cache makes this nearly instant.
|
||||
target "export-wheel-rocm" {
|
||||
inherits = ["_common-rocm"]
|
||||
target = "export_vllm"
|
||||
output = ["type=local,dest=./wheel-export"]
|
||||
}
|
||||
|
||||
target "final-rocm" {
|
||||
inherits = ["_common-rocm", "_labels"]
|
||||
target = "final"
|
||||
tags = ["rocm/vllm:latest"]
|
||||
output = ["type=docker"]
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
# docker-bake.hcl - vLLM Docker build configuration
|
||||
#
|
||||
# This file lives in vLLM repo at docker/docker-bake.hcl
|
||||
#
|
||||
# Usage:
|
||||
# cd docker && docker buildx bake # Build default target (openai)
|
||||
# cd docker && docker buildx bake test # Build test target
|
||||
# docker buildx bake --print # Show resolved config
|
||||
#
|
||||
# Reference: https://docs.docker.com/build/bake/reference/
|
||||
|
||||
# Build configuration
|
||||
|
||||
variable "MAX_JOBS" {
|
||||
default = 16
|
||||
}
|
||||
|
||||
variable "NVCC_THREADS" {
|
||||
default = 8
|
||||
}
|
||||
|
||||
variable "TORCH_CUDA_ARCH_LIST" {
|
||||
default = "8.0 8.9 9.0 10.0 11.0 12.0"
|
||||
}
|
||||
|
||||
variable "COMMIT" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "VLLM_BUILD_COMMIT" {
|
||||
default = "unknown"
|
||||
}
|
||||
|
||||
variable "VLLM_BUILD_PIPELINE" {
|
||||
default = "local"
|
||||
}
|
||||
|
||||
variable "VLLM_BUILD_URL" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "VLLM_IMAGE_TAG" {
|
||||
default = "local/vllm-openai:dev"
|
||||
}
|
||||
|
||||
# Groups
|
||||
|
||||
group "default" {
|
||||
targets = ["openai"]
|
||||
}
|
||||
|
||||
group "all" {
|
||||
targets = ["openai", "openai-ubuntu2404"]
|
||||
}
|
||||
|
||||
# Base targets
|
||||
|
||||
target "_common" {
|
||||
dockerfile = "docker/Dockerfile"
|
||||
context = "."
|
||||
args = {
|
||||
max_jobs = MAX_JOBS
|
||||
nvcc_threads = NVCC_THREADS
|
||||
torch_cuda_arch_list = TORCH_CUDA_ARCH_LIST
|
||||
VLLM_BUILD_COMMIT = VLLM_BUILD_COMMIT != "unknown" ? VLLM_BUILD_COMMIT : (COMMIT != "" ? COMMIT : "unknown")
|
||||
VLLM_BUILD_PIPELINE = VLLM_BUILD_PIPELINE
|
||||
VLLM_BUILD_URL = VLLM_BUILD_URL
|
||||
VLLM_IMAGE_TAG = VLLM_IMAGE_TAG
|
||||
}
|
||||
}
|
||||
|
||||
target "_labels" {
|
||||
labels = {
|
||||
"org.opencontainers.image.source" = "https://github.com/vllm-project/vllm"
|
||||
"org.opencontainers.image.vendor" = "vLLM"
|
||||
"org.opencontainers.image.title" = "vLLM"
|
||||
"org.opencontainers.image.description" = "vLLM: A high-throughput and memory-efficient inference and serving engine for LLMs"
|
||||
"org.opencontainers.image.licenses" = "Apache-2.0"
|
||||
"org.opencontainers.image.revision" = VLLM_BUILD_COMMIT != "unknown" ? VLLM_BUILD_COMMIT : (COMMIT != "" ? COMMIT : "unknown")
|
||||
"org.opencontainers.image.version" = VLLM_IMAGE_TAG
|
||||
"org.opencontainers.image.url" = VLLM_BUILD_URL
|
||||
"ai.vllm.build.commit" = VLLM_BUILD_COMMIT != "unknown" ? VLLM_BUILD_COMMIT : (COMMIT != "" ? COMMIT : "unknown")
|
||||
"ai.vllm.build.pipeline" = VLLM_BUILD_PIPELINE
|
||||
"ai.vllm.build.url" = VLLM_BUILD_URL
|
||||
"ai.vllm.image.tag" = VLLM_IMAGE_TAG
|
||||
}
|
||||
annotations = [
|
||||
"index,manifest:org.opencontainers.image.revision=${VLLM_BUILD_COMMIT != "unknown" ? VLLM_BUILD_COMMIT : (COMMIT != "" ? COMMIT : "unknown")}",
|
||||
]
|
||||
}
|
||||
|
||||
# Build targets
|
||||
|
||||
target "test" {
|
||||
inherits = ["_common", "_labels"]
|
||||
target = "test"
|
||||
tags = ["vllm:test"]
|
||||
output = ["type=docker"]
|
||||
}
|
||||
|
||||
target "openai" {
|
||||
inherits = ["_common", "_labels"]
|
||||
target = "vllm-openai"
|
||||
tags = ["vllm:openai"]
|
||||
output = ["type=docker"]
|
||||
}
|
||||
|
||||
# Ubuntu 24.04 targets
|
||||
|
||||
target "test-ubuntu2404" {
|
||||
inherits = ["_common", "_labels"]
|
||||
target = "test"
|
||||
tags = ["vllm:test-ubuntu24.04"]
|
||||
args = {
|
||||
UBUNTU_VERSION = "24.04"
|
||||
GDRCOPY_OS_VERSION = "Ubuntu24_04"
|
||||
}
|
||||
output = ["type=docker"]
|
||||
}
|
||||
|
||||
target "openai-ubuntu2404" {
|
||||
inherits = ["_common", "_labels"]
|
||||
target = "vllm-openai"
|
||||
tags = ["vllm:openai-ubuntu24.04"]
|
||||
args = {
|
||||
UBUNTU_VERSION = "24.04"
|
||||
GDRCOPY_OS_VERSION = "Ubuntu24_04"
|
||||
}
|
||||
output = ["type=docker"]
|
||||
}
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
#!/bin/sh
|
||||
# Shell-level unit test for vllm-nonroot-entrypoint.sh.
|
||||
#
|
||||
# Runs on the host (no Docker, no GPU) by stubbing `vllm` with a shim that
|
||||
# dumps its env + argv instead of actually serving. Exercises the wrapper's
|
||||
# HOME/USER fallback behavior that can't be easily tested from buildkite
|
||||
# (which would need a GPU to run `vllm serve --help`).
|
||||
#
|
||||
# Usage:
|
||||
# bash docker/entrypoints/test_vllm_nonroot_entrypoint.sh
|
||||
# Exits non-zero on the first failed assertion.
|
||||
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
WRAPPER="${SCRIPT_DIR}/vllm-nonroot-entrypoint.sh"
|
||||
|
||||
if [ ! -x "$WRAPPER" ]; then
|
||||
echo "FAIL: wrapper not found or not executable: $WRAPPER" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WORKDIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$WORKDIR"' EXIT
|
||||
|
||||
# Stub `vllm` on PATH. It dumps env + argv + cwd to stdout so we can assert.
|
||||
mkdir -p "$WORKDIR/bin"
|
||||
cat > "$WORKDIR/bin/vllm" <<'EOF'
|
||||
#!/bin/sh
|
||||
echo "ARGV=$*"
|
||||
echo "HOME=${HOME-__unset__}"
|
||||
echo "USER=${USER-__unset__}"
|
||||
echo "LOGNAME=${LOGNAME-__unset__}"
|
||||
echo "PWD=$(pwd)"
|
||||
EOF
|
||||
chmod +x "$WORKDIR/bin/vllm"
|
||||
|
||||
run_wrapper() {
|
||||
# Usage: run_wrapper <output_file> <env_kv>... -- <wrapper_arg>...
|
||||
_out="$1"; shift
|
||||
_env=""
|
||||
while [ "${1:-}" != "--" ]; do
|
||||
_env="$_env $1"; shift
|
||||
done
|
||||
shift
|
||||
env -i PATH="$WORKDIR/bin:/usr/bin:/bin" $_env "$WRAPPER" "$@" > "$_out"
|
||||
}
|
||||
|
||||
fail() { echo "FAIL: $*" >&2; echo "--- stdout ---" >&2; cat "$1" >&2; exit 1; }
|
||||
|
||||
expect_default_home() {
|
||||
_out="$1"
|
||||
_case="$2"
|
||||
if [ -w /home/vllm ]; then
|
||||
expected_home="/home/vllm"
|
||||
grep -q "^HOME=$expected_home\$" "$_out" \
|
||||
|| fail "$_out" "$_case: HOME not set to $expected_home"
|
||||
else
|
||||
expected_home="/tmp/vllm-home.XXXXXX"
|
||||
grep -Eq '^HOME=/tmp/vllm-home\.[^/]+$' "$_out" \
|
||||
|| fail "$_out" "$_case: HOME not set to $expected_home"
|
||||
fi
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Case 1: writable HOME and USER both set -> wrapper must leave them alone.
|
||||
# -----------------------------------------------------------------------------
|
||||
case1_home="$WORKDIR/case1-home"
|
||||
mkdir -p "$case1_home"
|
||||
out="$WORKDIR/case1.out"
|
||||
run_wrapper "$out" "HOME=$case1_home" "USER=alice" "LOGNAME=alice" -- --model foo
|
||||
grep -q "^HOME=$case1_home\$" "$out" || fail "$out" "case1: HOME not preserved"
|
||||
grep -q "^USER=alice\$" "$out" || fail "$out" "case1: USER not preserved"
|
||||
grep -q "^LOGNAME=alice\$" "$out" || fail "$out" "case1: LOGNAME not preserved"
|
||||
grep -q "^ARGV=serve --model foo\$" "$out" || fail "$out" "case1: ARGV wrong"
|
||||
echo "PASS: case1 (writable HOME + USER preserved)"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Case 2: HOME unset -> falls back to /home/vllm if writable, else
|
||||
# /tmp/vllm-home.XXXXXX.
|
||||
# -----------------------------------------------------------------------------
|
||||
# The wrapper checks whether the real /home/vllm exists and is writable. On
|
||||
# dev machines /home/vllm typically does NOT exist, so the
|
||||
# wrapper should fall to /tmp/vllm-home.XXXXXX.
|
||||
out="$WORKDIR/case2.out"
|
||||
run_wrapper "$out" -- --model bar
|
||||
expect_default_home "$out" "case2"
|
||||
grep -q "^USER=vllm\$" "$out" || fail "$out" "case2: USER not defaulted to vllm"
|
||||
grep -q "^LOGNAME=vllm\$" "$out" || fail "$out" "case2: LOGNAME not defaulted to vllm"
|
||||
grep -q "^ARGV=serve --model bar\$" "$out" || fail "$out" "case2: ARGV wrong"
|
||||
echo "PASS: case2 (unset HOME falls back to $expected_home, USER defaulted)"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Case 3: HOME set but unwritable -> must also fall back.
|
||||
# -----------------------------------------------------------------------------
|
||||
ro_home="$WORKDIR/ro-home"
|
||||
mkdir -p "$ro_home"
|
||||
chmod 0500 "$ro_home"
|
||||
out="$WORKDIR/case3.out"
|
||||
run_wrapper "$out" "HOME=$ro_home" -- --model baz
|
||||
expect_default_home "$out" "case3"
|
||||
grep -q "^USER=vllm\$" "$out" || fail "$out" "case3: USER not defaulted"
|
||||
chmod 0700 "$ro_home"
|
||||
echo "PASS: case3 (unwritable HOME overridden)"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Case 4: USER set but LOGNAME unset -> LOGNAME mirrors USER.
|
||||
# -----------------------------------------------------------------------------
|
||||
case4_home="$WORKDIR/case4-home"
|
||||
mkdir -p "$case4_home"
|
||||
out="$WORKDIR/case4.out"
|
||||
run_wrapper "$out" "HOME=$case4_home" "USER=carol" -- --model qux
|
||||
grep -q "^USER=carol\$" "$out" || fail "$out" "case4: USER not preserved"
|
||||
grep -q "^LOGNAME=carol\$" "$out" || fail "$out" "case4: LOGNAME not mirrored from USER"
|
||||
echo "PASS: case4 (LOGNAME mirrors USER when unset)"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Case 5: /etc/passwd is writable AND the current UID is not in it -> wrapper
|
||||
# appends a synthetic entry. Uses the VLLM_PASSWD_FILE test hook so we don't
|
||||
# touch the real /etc/passwd.
|
||||
# -----------------------------------------------------------------------------
|
||||
fake_passwd="$WORKDIR/fake-passwd"
|
||||
: > "$fake_passwd" # empty file, current UID definitely not present
|
||||
case5_home="$WORKDIR/case5-home"
|
||||
mkdir -p "$case5_home"
|
||||
out="$WORKDIR/case5.out"
|
||||
run_wrapper "$out" "HOME=$case5_home" "VLLM_PASSWD_FILE=$fake_passwd" -- --model foo
|
||||
current_uid="$(id -u)"
|
||||
current_gid="$(id -g)"
|
||||
expected_line="vllm:x:${current_uid}:${current_gid}:vllm:${case5_home}:/bin/bash"
|
||||
grep -Fx "$expected_line" "$fake_passwd" > /dev/null \
|
||||
|| { echo "FAIL: case5: expected line not found in fake passwd:"; echo " expected: $expected_line"; echo " file contents:"; cat "$fake_passwd"; exit 1; }
|
||||
echo "PASS: case5 (passwd entry appended for arbitrary UID)"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Case 6: /etc/passwd is writable but current UID already has an entry ->
|
||||
# wrapper must NOT duplicate the entry.
|
||||
# -----------------------------------------------------------------------------
|
||||
fake_passwd="$WORKDIR/fake-passwd-prepopulated"
|
||||
printf 'vllm:x:%s:%s:vllm:/home/vllm:/bin/bash\n' "$current_uid" "$current_gid" > "$fake_passwd"
|
||||
out="$WORKDIR/case6.out"
|
||||
run_wrapper "$out" "HOME=$case5_home" "VLLM_PASSWD_FILE=$fake_passwd" -- --model foo
|
||||
line_count="$(wc -l < "$fake_passwd")"
|
||||
# NOTE: wc may count 0 or 1 depending on trailing newline; accept 1.
|
||||
# More robust: count lines matching our UID.
|
||||
uid_lines="$(grep -c ":${current_uid}:" "$fake_passwd" || true)"
|
||||
[ "$uid_lines" = "1" ] \
|
||||
|| { echo "FAIL: case6: expected exactly one entry for UID $current_uid, got $uid_lines"; cat "$fake_passwd"; exit 1; }
|
||||
echo "PASS: case6 (existing passwd entry not duplicated)"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Case 7: /etc/passwd is NOT writable -> wrapper must NOT crash, just skip.
|
||||
# Skipped when running as root, because root's DAC override means [ -w ... ]
|
||||
# is always true regardless of mode bits -- the case can't be simulated.
|
||||
# In the real deployment (non-root UID inside the container) this IS the
|
||||
# relevant behavior and is what `_passwd_file is not writable` encodes.
|
||||
# -----------------------------------------------------------------------------
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
echo "SKIP: case7 (running as root; DAC override makes unwritable check meaningless)"
|
||||
else
|
||||
fake_passwd="$WORKDIR/ro-passwd"
|
||||
: > "$fake_passwd"
|
||||
chmod 0444 "$fake_passwd"
|
||||
out="$WORKDIR/case7.out"
|
||||
run_wrapper "$out" "HOME=$case5_home" "VLLM_PASSWD_FILE=$fake_passwd" -- --model foo
|
||||
# File must remain empty (no write happened) and the wrapper exec'd
|
||||
# `vllm serve` successfully (stdout contains ARGV line).
|
||||
[ ! -s "$fake_passwd" ] \
|
||||
|| { echo "FAIL: case7: RO passwd file was modified"; cat "$fake_passwd"; exit 1; }
|
||||
grep -q "^ARGV=serve --model foo\$" "$out" || fail "$out" "case7: wrapper didn't exec vllm"
|
||||
chmod 0600 "$fake_passwd"
|
||||
echo "PASS: case7 (unwritable passwd file tolerated)"
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Case 8: caller's writable CWD is preserved — wrapper must NOT chdir to HOME
|
||||
# when cwd is usable. Protects relative-path workflows like
|
||||
# `docker run -w /models ... --model ./llama.gguf`.
|
||||
# -----------------------------------------------------------------------------
|
||||
case8_home="$WORKDIR/case8-home"
|
||||
mkdir -p "$case8_home"
|
||||
case8_cwd="$WORKDIR/case8-cwd"
|
||||
mkdir -p "$case8_cwd"
|
||||
out="$WORKDIR/case8.out"
|
||||
(cd "$case8_cwd" && run_wrapper "$out" "HOME=$case8_home" "USER=alice" "LOGNAME=alice" -- --model ./relpath)
|
||||
grep -q "^PWD=$case8_cwd\$" "$out" \
|
||||
|| fail "$out" "case8: writable cwd not preserved (got $(grep '^PWD=' "$out"))"
|
||||
grep -q "^ARGV=serve --model \\./relpath\$" "$out" \
|
||||
|| fail "$out" "case8: relative argv not preserved"
|
||||
echo "PASS: case8 (writable cwd preserved; relative argv still resolves from caller's cwd)"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Case 9: read-only cwd is ALSO preserved. A caller who mounts a read-only
|
||||
# model directory at the container's cwd (e.g. `docker run -w /models` with
|
||||
# /models bind-mounted ro) expects relative argv like `--model ./foo.gguf`
|
||||
# to resolve against /models. An earlier version of this wrapper rewrote
|
||||
# read-only cwd to $HOME and broke that workflow; this case guards against
|
||||
# the regression returning.
|
||||
# -----------------------------------------------------------------------------
|
||||
case9_home="$WORKDIR/case9-home"
|
||||
mkdir -p "$case9_home"
|
||||
case9_ro="$WORKDIR/case9-ro"
|
||||
mkdir -p "$case9_ro"
|
||||
chmod 0555 "$case9_ro"
|
||||
out="$WORKDIR/case9.out"
|
||||
(cd "$case9_ro" && run_wrapper "$out" "HOME=$case9_home" "USER=alice" "LOGNAME=alice" -- --model ./foo)
|
||||
grep -q "^PWD=$case9_ro\$" "$out" \
|
||||
|| fail "$out" "case9: read-only cwd was rewritten (got $(grep '^PWD=' "$out"))"
|
||||
grep -q "^ARGV=serve --model \\./foo\$" "$out" \
|
||||
|| fail "$out" "case9: relative argv not preserved"
|
||||
chmod 0700 "$case9_ro"
|
||||
echo "PASS: case9 (read-only cwd preserved; relative argv still resolves from caller's cwd)"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Case 10: truly inaccessible cwd (no search bit) DOES fall back to $HOME.
|
||||
# Skipped as root because DAC override lets root cd into 0000 directories.
|
||||
# -----------------------------------------------------------------------------
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
echo "SKIP: case10 (running as root; DAC override makes inaccessible cwd untestable)"
|
||||
else
|
||||
case10_home="$WORKDIR/case10-home"
|
||||
mkdir -p "$case10_home"
|
||||
case10_cwd="$WORKDIR/case10-cwd"
|
||||
mkdir -p "$case10_cwd"
|
||||
out="$WORKDIR/case10.out"
|
||||
# Make cwd genuinely inaccessible (mode 0000 = no search bit -> cd .
|
||||
# fails with EACCES). Use absolute paths for chmod so our own test
|
||||
# cleanup still works without needing search perm on the dir.
|
||||
(
|
||||
cd "$case10_cwd"
|
||||
chmod 0000 "$case10_cwd"
|
||||
run_wrapper "$out" "HOME=$case10_home" "USER=alice" "LOGNAME=alice" -- --model foo
|
||||
)
|
||||
chmod 0700 "$case10_cwd"
|
||||
grep -q "^PWD=$case10_home\$" "$out" \
|
||||
|| fail "$out" "case10: inaccessible cwd not overridden to HOME (got $(grep '^PWD=' "$out"))"
|
||||
echo "PASS: case10 (inaccessible cwd falls back to \$HOME)"
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Case 11: if /tmp cannot create a private fallback dir, wrapper uses /tmp as
|
||||
# the last-resort HOME instead of leaving HOME empty under set -eu.
|
||||
# -----------------------------------------------------------------------------
|
||||
if [ -w /home/vllm ]; then
|
||||
echo "SKIP: case11 (/home/vllm is writable; mktemp fallback path is not used)"
|
||||
else
|
||||
cat > "$WORKDIR/bin/mktemp" <<'EOF'
|
||||
#!/bin/sh
|
||||
exit 1
|
||||
EOF
|
||||
chmod +x "$WORKDIR/bin/mktemp"
|
||||
|
||||
out="$WORKDIR/case11.out"
|
||||
run_wrapper "$out" -- --model no-mktemp
|
||||
rm -f "$WORKDIR/bin/mktemp"
|
||||
|
||||
grep -q "^HOME=/tmp\$" "$out" \
|
||||
|| fail "$out" "case11: mktemp failure did not fall back to /tmp"
|
||||
grep -q "^USER=vllm\$" "$out" || fail "$out" "case11: USER not defaulted"
|
||||
grep -q "^LOGNAME=vllm\$" "$out" || fail "$out" "case11: LOGNAME not defaulted"
|
||||
grep -q "^ARGV=serve --model no-mktemp\$" "$out" || fail "$out" "case11: ARGV wrong"
|
||||
echo "PASS: case11 (mktemp failure falls back to /tmp)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "ALL CASES PASSED."
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
#!/bin/sh
|
||||
# Entrypoint wrapper for the opt-in `vllm-openai-nonroot` image.
|
||||
#
|
||||
# The image also ships a `vllm` user (UID 2000, GID 0) with HOME /home/vllm
|
||||
# and a group-0-writable home directory. When the container is launched with
|
||||
# `--user 2000:0` (or any other UID in group 0) the passwd entry is enough on
|
||||
# its own: Docker picks up HOME=/home/vllm, getpass.getuser() resolves to
|
||||
# "vllm", and every cache dir (HF, Triton, Inductor, vLLM, Numba, Outlines)
|
||||
# that defaults to `$HOME/.cache/...` lands in a writable location.
|
||||
#
|
||||
# This wrapper exists for the *arbitrary-UID* case (e.g. OpenShift's
|
||||
# `runAsUser: 1000540000` Restricted Pod Security Standard) where the caller
|
||||
# UID is not in /etc/passwd at all. In that case:
|
||||
# * $HOME may be unset or resolve to "/" (unwritable).
|
||||
# * getpass.getuser() falls back to pwd.getpwuid() -> KeyError.
|
||||
#
|
||||
# The wrapper re-points $HOME to /home/vllm when writable, /tmp/vllm-home.XXXXXX
|
||||
# otherwise, and defaults $USER to "vllm" so the pwd-lookup path is never
|
||||
# taken. Everything else is forwarded to `vllm serve`.
|
||||
#
|
||||
# Non-empty caller-set env vars (HOME, USER, LOGNAME) are preserved, so
|
||||
# existing K8s manifests and `docker run -e ...` keep working unchanged.
|
||||
# Unset or empty values fall through to the wrapper's defaults, matching
|
||||
# what shell code typically expects from "unset".
|
||||
|
||||
set -eu
|
||||
|
||||
if [ -z "${HOME:-}" ] || [ ! -w "${HOME}" ]; then
|
||||
if [ -w /home/vllm ]; then
|
||||
export HOME=/home/vllm
|
||||
else
|
||||
if _h="$(mktemp -d /tmp/vllm-home.XXXXXX 2>/dev/null)"; then
|
||||
export HOME="$_h"
|
||||
chmod 0700 "$HOME" 2>/dev/null || true
|
||||
else
|
||||
export HOME=/tmp
|
||||
fi
|
||||
unset _h
|
||||
fi
|
||||
fi
|
||||
|
||||
# Preserve the caller's cwd whenever it's still usable. A read-only mount
|
||||
# (e.g. `docker run -w /models ... --model ./llama.gguf` where /models is
|
||||
# the user's model share) is a legitimate, usable cwd — vllm only needs to
|
||||
# *read* relative paths from there. We only fall back to $HOME when the
|
||||
# cwd itself is truly inaccessible (no search bit, deleted inode, mount
|
||||
# gone, etc.), which is when `cd .` actually fails.
|
||||
#
|
||||
# This is the accessibility check, not a writability check; the latter
|
||||
# would silently rewrite cwd for any read-only workflow and break relative
|
||||
# argv like `--model ./llama.gguf`, `--chat-template ./t.jinja`, relative
|
||||
# TLS cert paths, etc.
|
||||
if ! cd . 2>/dev/null; then
|
||||
cd "$HOME"
|
||||
fi
|
||||
|
||||
# getpass.getuser() prefers $USER/$LOGNAME/etc. before hitting getpwuid();
|
||||
# setting it here makes the "UID not in passwd" path a no-op for everything
|
||||
# in the process tree.
|
||||
if [ -z "${USER:-}" ]; then
|
||||
export USER=vllm
|
||||
fi
|
||||
if [ -z "${LOGNAME:-}" ]; then
|
||||
export LOGNAME="$USER"
|
||||
fi
|
||||
|
||||
# Shell-level tooling (`whoami`, bash's `\u` prompt, `id -un`, `sudo`) does
|
||||
# NOT consult $USER; it calls getpwuid(geteuid()) directly. For arbitrary
|
||||
# runtime UIDs in OpenShift-style deploys this returns "I have no name!".
|
||||
# If /etc/passwd is group-0 writable (set at build time) and doesn't yet
|
||||
# have an entry for this UID, append a synthetic one so every downstream
|
||||
# consumer sees a consistent "vllm" identity.
|
||||
#
|
||||
# We parse the passwd file directly instead of calling `getent` because
|
||||
# the container's NSS is typically just files anyway, and this lets us
|
||||
# unit-test via the VLLM_PASSWD_FILE hook (undocumented; production uses
|
||||
# /etc/passwd).
|
||||
_passwd_file="${VLLM_PASSWD_FILE:-/etc/passwd}"
|
||||
_uid="$(id -u)"
|
||||
if [ -w "$_passwd_file" ] \
|
||||
&& ! awk -F: -v u="$_uid" '$3==u {found=1; exit} END {exit !found}' "$_passwd_file" 2>/dev/null; then
|
||||
printf 'vllm:x:%s:%s:vllm:%s:/bin/bash\n' \
|
||||
"$_uid" "$(id -g)" "$HOME" >> "$_passwd_file"
|
||||
fi
|
||||
unset _uid _passwd_file
|
||||
|
||||
exec vllm serve "$@"
|
||||
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"_comment": "Auto-generated from Dockerfile ARGs. Do not edit manually. Run: python tools/generate_versions_json.py",
|
||||
"variable": {
|
||||
"CUDA_VERSION": {
|
||||
"default": "13.0.2"
|
||||
},
|
||||
"PYTHON_VERSION": {
|
||||
"default": "3.12"
|
||||
},
|
||||
"UBUNTU_VERSION": {
|
||||
"default": "22.04"
|
||||
},
|
||||
"BUILD_BASE_IMAGE": {
|
||||
"default": "nvidia/cuda:13.0.2-devel-ubuntu22.04"
|
||||
},
|
||||
"FINAL_BASE_IMAGE": {
|
||||
"default": "nvidia/cuda:13.0.2-base-ubuntu22.04"
|
||||
},
|
||||
"BUILD_OS": {
|
||||
"default": "ubuntu"
|
||||
},
|
||||
"GET_PIP_URL": {
|
||||
"default": "https://bootstrap.pypa.io/get-pip.py"
|
||||
},
|
||||
"PYTORCH_CUDA_INDEX_BASE_URL": {
|
||||
"default": "https://download.pytorch.org/whl"
|
||||
},
|
||||
"PIP_KEYRING_PROVIDER": {
|
||||
"default": "disabled"
|
||||
},
|
||||
"UV_KEYRING_PROVIDER": {
|
||||
"default": "disabled"
|
||||
},
|
||||
"INSTALL_KV_CONNECTORS": {
|
||||
"default": "false"
|
||||
},
|
||||
"SCCACHE_BUCKET_NAME": {
|
||||
"default": "vllm-build-sccache"
|
||||
},
|
||||
"SCCACHE_REGION_NAME": {
|
||||
"default": "us-west-2"
|
||||
},
|
||||
"SCCACHE_S3_NO_CREDENTIALS": {
|
||||
"default": "0"
|
||||
},
|
||||
"TORCH_CUDA_ARCH_LIST": {
|
||||
"default": "7.5 8.0 8.6 8.9 9.0 10.0 11.0 12.0"
|
||||
},
|
||||
"MAX_JOBS": {
|
||||
"default": "2"
|
||||
},
|
||||
"NVCC_THREADS": {
|
||||
"default": "8"
|
||||
},
|
||||
"vllm_target_device": {
|
||||
"default": "cuda"
|
||||
},
|
||||
"DEEPEP_COMMIT_HASH": {
|
||||
"default": "73b6ea4"
|
||||
},
|
||||
"GIT_REPO_CHECK": {
|
||||
"default": "0"
|
||||
},
|
||||
"VLLM_MAX_SIZE_MB": {
|
||||
"default": "500"
|
||||
},
|
||||
"RUN_WHEEL_CHECK": {
|
||||
"default": "true"
|
||||
},
|
||||
"FLASHINFER_VERSION": {
|
||||
"default": "0.6.13"
|
||||
},
|
||||
"GDRCOPY_CUDA_VERSION": {
|
||||
"default": "12.8"
|
||||
},
|
||||
"GDRCOPY_OS_VERSION": {
|
||||
"default": "Ubuntu22_04"
|
||||
},
|
||||
"BITSANDBYTES_VERSION_X86": {
|
||||
"default": "0.46.1"
|
||||
},
|
||||
"BITSANDBYTES_VERSION_ARM64": {
|
||||
"default": "0.42.0"
|
||||
},
|
||||
"TIMM_VERSION": {
|
||||
"default": ">=1.0.17"
|
||||
},
|
||||
"RUNAI_MODEL_STREAMER_VERSION": {
|
||||
"default": ">=0.15.7"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user