| 1 | ######################### RUST BUILD IMAGE ######################### |
| 2 | # Build the Rust frontend (`vllm-rs`) in a dedicated stage so the main image |
| 3 | # doesn't need the rust toolchain. Runs in parallel with vllm-base. |
| 4 | FROM ubuntu:22.04 AS rust-build-cache |
| 5 | ENV DEBIAN_FRONTEND=noninteractive |
| 6 | |
| 7 | RUN apt-get update -y \ |
| 8 | && apt-get install -y --no-install-recommends \ |
| 9 | ca-certificates curl git build-essential python3 python3-pip \ |
| 10 | && rm -rf /var/lib/apt/lists/* |
| 11 | |
| 12 | WORKDIR /workspace |
| 13 | |
| 14 | COPY requirements/build/rust.txt requirements/build/rust.txt |
| 15 | RUN python3 -m pip install --no-cache-dir -r requirements/build/rust.txt |
| 16 | |
| 17 | # Copy only the Rust build inputs; tools/build_rust.sh publishes artifacts needed |
| 18 | # by the wheel build stage. |
| 19 | COPY rust rust |
| 20 | COPY rust-toolchain.toml rust-toolchain.toml |
| 21 | COPY tools/build_rust.py tools/build_rust.py |
| 22 | COPY tools/build_rust.sh tools/build_rust.sh |
| 23 | |
| 24 | # Cap cargo parallelism to avoid exhausting the CI host's open-file limit |
| 25 | # (rustc spawns enough concurrent processes to hit RLIMIT_NOFILE otherwise). |
| 26 | ENV CARGO_BUILD_JOBS=4 |
| 27 | |
| 28 | # Build with a stable version so this target snapshot is keyed only by Rust |
| 29 | # inputs. The child stage below relinks the crates that embed the exact version. |
| 30 | RUN --mount=type=cache,target=/root/.cargo/registry,sharing=locked \ |
| 31 | --mount=type=cache,target=/root/.cargo/git,sharing=locked \ |
| 32 | SETUPTOOLS_SCM_PRETEND_VERSION="0.0.0+docker.cache" bash tools/build_rust.sh |
| 33 | |
| 34 | # Relink with the exact Git-derived package version. |
| 35 | FROM rust-build-cache AS rust-build |
| 36 | |
| 37 | RUN --mount=type=cache,target=/root/.cargo/registry,sharing=locked \ |
| 38 | --mount=type=cache,target=/root/.cargo/git,sharing=locked \ |
| 39 | --mount=type=bind,source=.git,target=.git \ |
| 40 | SETUPTOOLS_SCM_PRETEND_METADATA="{dirty=false}" bash tools/build_rust.sh |
| 41 | |
| 42 | FROM ubuntu:24.04 AS vllm-base |
| 43 | |
| 44 | ENV DEBIAN_FRONTEND=noninteractive |
| 45 | |
| 46 | WORKDIR /workspace/ |
| 47 | |
| 48 | ARG PYTHON_VERSION=3.12 |
| 49 | ARG PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/xpu" |
| 50 | |
| 51 | RUN apt-get update -y && \ |
| 52 | apt-get install -y --no-install-recommends \ |
| 53 | build-essential \ |
| 54 | curl \ |
| 55 | ffmpeg \ |
| 56 | git \ |
| 57 | gpg \ |
| 58 | libsndfile1 \ |
| 59 | libsm6 \ |
| 60 | libxext6 \ |
| 61 | libgl1 \ |
| 62 | lsb-release \ |
| 63 | libaio-dev \ |
| 64 | numactl \ |
| 65 | wget \ |
| 66 | vim \ |
| 67 | ca-certificates \ |
| 68 | python3.12 \ |
| 69 | python3.12-dev \ |
| 70 | python3-pip && \ |
| 71 | rm -rf /var/lib/apt/lists/* |
| 72 | |
| 73 | # Install UMD |
| 74 | RUN mkdir neo && \ |
| 75 | cd neo && \ |
| 76 | wget https://github.com/intel/intel-graphics-compiler/releases/download/v2.38.2/intel-igc-core-2_2.38.2+22051_amd64.deb && \ |
| 77 | wget https://github.com/intel/intel-graphics-compiler/releases/download/v2.38.2/intel-igc-opencl-2_2.38.2+22051_amd64.deb && \ |
| 78 | wget https://github.com/intel/compute-runtime/releases/download/26.27.39122.11/intel-ocloc_26.27.39122.11-0_amd64.deb && \ |
| 79 | wget https://github.com/intel/compute-runtime/releases/download/26.27.39122.11/intel-opencl-icd_26.27.39122.11-0_amd64.deb && \ |
| 80 | wget https://github.com/intel/compute-runtime/releases/download/26.27.39122.11/libigdgmm12_22.10.0_amd64.deb && \ |
| 81 | wget https://github.com/intel/compute-runtime/releases/download/26.27.39122.11/libze-intel-gpu1_26.27.39122.11-0_amd64.deb && \ |
| 82 | wget https://github.com/oneapi-src/level-zero/releases/download/v1.32.0/libze1_1.32.0+u24.04_amd64.deb && \ |
| 83 | wget https://github.com/oneapi-src/level-zero/releases/download/v1.32.0/libze-dev_1.32.0+u24.04_amd64.deb && \ |
| 84 | dpkg -i *.deb && \ |
| 85 | cd .. && \ |
| 86 | rm -rf neo |
| 87 | |
| 88 | # Install XPU-Manager payloads without registering conflicting libze package |
| 89 | # dependencies in dpkg. |
| 90 | # Note that ocl-icd-opencl-dev is required by DLE upgrade but xpu-smi, should |
| 91 | # can be removed in future. |
| 92 | RUN apt-get update -y && \ |
| 93 | apt-get install -y --no-install-recommends software-properties-common && \ |
| 94 | add-apt-repository -y ppa:kobuk-team/intel-graphics && \ |
| 95 | apt-get update -y && \ |
| 96 | apt-get install -y --no-install-recommends libhwloc15 libpciaccess0 libigsc1 intel-metrics-library && \ |
| 97 | apt-get install -y ocl-icd-opencl-dev && \ |
| 98 | mkdir xpu-m && \ |
| 99 | cd xpu-m && \ |
| 100 | wget https://github.com/intel/xpumanager/releases/download/v2.1.0/xpu-smi_2.1.0+26.33.6468cec-1.24.04_amd64.deb && \ |
| 101 | apt install -y ./xpu-smi_2.1.0+26.33.6468cec-1.24.04_amd64.deb --install-suggests && \ |
| 102 | cd .. && \ |
| 103 | rm -rf xpu-m && \ |
| 104 | add-apt-repository --remove -y ppa:kobuk-team/intel-graphics && \ |
| 105 | apt-get update -y |
| 106 | |
| 107 | ENV PATH="/root/.local/bin:$PATH" |
| 108 | ENV VIRTUAL_ENV="/opt/venv" |
| 109 | ENV UV_PYTHON_INSTALL_DIR=/opt/uv/python |
| 110 | RUN curl -LsSf https://astral.sh/uv/install.sh | sh \ |
| 111 | && uv venv --python ${PYTHON_VERSION} --seed ${VIRTUAL_ENV} |
| 112 | ENV PATH="$VIRTUAL_ENV/bin:$PATH" |
| 113 | |
| 114 | SHELL ["bash", "-c"] |
| 115 | CMD ["bash", "-c", "source /root/.bashrc && exec bash"] |
| 116 | |
| 117 | WORKDIR /workspace/vllm |
| 118 | |
| 119 | ENV UV_HTTP_TIMEOUT=500 |
| 120 | |
| 121 | # Configure package index for XPU |
| 122 | ENV PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL} |
| 123 | ENV UV_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL} |
| 124 | ENV UV_INDEX_STRATEGY="unsafe-best-match" |
| 125 | ENV UV_LINK_MODE="copy" |
| 126 | |
| 127 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 128 | --mount=type=bind,src=requirements/common.txt,target=/workspace/vllm/requirements/common.txt \ |
| 129 | --mount=type=bind,src=requirements/xpu.txt,target=/workspace/vllm/requirements/xpu.txt \ |
| 130 | uv pip install --upgrade pip |
| 131 | |
| 132 | |
| 133 | ENV LD_LIBRARY_PATH=/opt/venv/lib:/usr/local/lib |
| 134 | CMD ["/bin/bash"] |
| 135 | |
| 136 | ######################### UCX + NIXL BUILD STAGE ######################### |
| 137 | # Build UCX and NIXL in a dedicated stage so compiler/autotools layers are |
| 138 | # never included in the final runtime image (mirrors ROCm's build_rixl stage). |
| 139 | ######################### WHEEL BUILD STAGE ######################### |
| 140 | # Produces a standalone dist/*.whl artifact (used by the release pipeline's |
| 141 | # "Build wheel - XPU" step), independent of the runtime image below. |
| 142 | FROM vllm-base AS vllm-build |
| 143 | |
| 144 | ARG GIT_REPO_CHECK=0 |
| 145 | |
| 146 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 147 | --mount=type=bind,src=requirements/common.txt,target=/workspace/vllm/requirements/common.txt \ |
| 148 | --mount=type=bind,src=requirements/xpu.txt,target=/workspace/vllm/requirements/xpu.txt \ |
| 149 | uv pip install grpcio-tools protobuf nanobind && \ |
| 150 | uv pip install -r /workspace/vllm/requirements/xpu.txt |
| 151 | |
| 152 | # Keep source-dependent layers near the end so frequent code-only changes |
| 153 | # don't invalidate heavy dependency layers. |
| 154 | COPY . . |
| 155 | |
| 156 | # Drop the pre-built Rust artifacts into the source tree. setup.py detects |
| 157 | # them and ships them as-is, skipping the local Rust build. |
| 158 | COPY --from=rust-build /workspace/vllm/vllm-rs vllm/vllm-rs |
| 159 | COPY --from=rust-build /workspace/vllm/_rust_*.so vllm/ |
| 160 | |
| 161 | RUN --mount=type=bind,source=.git,target=.git \ |
| 162 | if [ "$GIT_REPO_CHECK" != 0 ]; then bash tools/check_repo.sh; fi |
| 163 | |
| 164 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 165 | --mount=type=bind,source=.git,target=.git \ |
| 166 | VLLM_TARGET_DEVICE=xpu python3 setup.py bdist_wheel --dist-dir=dist --py-limited-api=cp38 |
| 167 | |
| 168 | FROM vllm-base AS ucx-nixl-build |
| 169 | |
| 170 | # Keep UCX_VERSION aligned with the UCX that NIXL itself builds against for this |
| 171 | # NIXL_VERSION (nixl contrib/Dockerfile.manylinux: ARG UCX_REF), so XPU runs the |
| 172 | # same UCX commit as the released nixl-cu* wheels rather than an untested pairing. |
| 173 | ARG UCX_VERSION=v1.21.x |
| 174 | ARG NIXL_VERSION=v1.3.2 |
| 175 | |
| 176 | # Build-time only: compiler, autotools, and verbs dev headers |
| 177 | RUN apt-get update -y && apt-get install -y --no-install-recommends \ |
| 178 | build-essential \ |
| 179 | autoconf \ |
| 180 | automake \ |
| 181 | libtool \ |
| 182 | pkg-config \ |
| 183 | libibverbs-dev \ |
| 184 | librdmacm-dev \ |
| 185 | && rm -rf /var/lib/apt/lists/* |
| 186 | |
| 187 | # Build UCX and produce a NIXL wheel so the final image needs no compiler. |
| 188 | # patchelf (installed via uv) is used by the NIXL wheel build to rewrite |
| 189 | # RPATH entries, making the wheel portable across stages. |
| 190 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 191 | git clone --depth 1 --branch "${UCX_VERSION}" https://github.com/openucx/ucx /tmp/ucx_source && \ |
| 192 | cd /tmp/ucx_source && \ |
| 193 | bash autogen.sh && \ |
| 194 | ./configure --prefix=/opt/ucx --with-ze=yes --enable-examples --enable-mt && \ |
| 195 | make CFLAGS="-Wno-error=incompatible-pointer-types" -j"$(nproc)" && make install && \ |
| 196 | git clone --depth 1 --branch "${NIXL_VERSION}" https://github.com/ai-dynamo/nixl /tmp/nixl_source && \ |
| 197 | cd /tmp/nixl_source && \ |
| 198 | uv pip install --upgrade meson pybind11 patchelf && \ |
| 199 | uv pip install -r requirements.txt && \ |
| 200 | PKG_CONFIG_PATH=/opt/ucx/lib/pkgconfig \ |
| 201 | LD_LIBRARY_PATH=/opt/ucx/lib \ |
| 202 | python -m pip wheel --no-deps . -w /tmp/nixl_wheels/ && \ |
| 203 | find /opt/ucx -type f \( -name '*.a' -o -name '*.la' \) -delete && \ |
| 204 | rm -rf /opt/ucx/{include,share,etc} /opt/ucx/lib/cmake \ |
| 205 | /tmp/ucx_source /tmp/nixl_source |
| 206 | |
| 207 | FROM vllm-base AS vllm-openai |
| 208 | ENV UV_COMPILE_BYTECODE=1 |
| 209 | |
| 210 | # Must match the ucx-nixl-build stage above: ARG does not cross stages, so a stale |
| 211 | # value here installs a meta package that disagrees with the wheel built there. |
| 212 | ARG NIXL_VERSION=v1.3.2 |
| 213 | |
| 214 | # Copy compiled UCX runtime libraries and the pre-built NIXL wheel. |
| 215 | # No compiler or autotools are installed in this stage. |
| 216 | COPY --from=ucx-nixl-build /opt/ucx /opt/ucx |
| 217 | COPY --from=ucx-nixl-build /tmp/nixl_wheels /tmp/nixl_wheels |
| 218 | |
| 219 | ENV LD_LIBRARY_PATH=/opt/ucx/lib:${LD_LIBRARY_PATH} |
| 220 | |
| 221 | # Install RDMA runtime libraries (no build tools) and the pre-built NIXL wheel. |
| 222 | # Do not uninstall/reinstall large Python packages here to avoid extra layer |
| 223 | # churn; final package resolution remains in the later app install step. |
| 224 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 225 | apt-get update -y && apt-get install -y --no-install-recommends \ |
| 226 | rdma-core \ |
| 227 | libibverbs1 \ |
| 228 | librdmacm1 \ |
| 229 | libibumad3 \ |
| 230 | libibmad5 \ |
| 231 | libmlx5-1 \ |
| 232 | libmlx4-1 \ |
| 233 | ibverbs-providers \ |
| 234 | librdmacm1t64 \ |
| 235 | && rm -rf /var/lib/apt/lists/* \ |
| 236 | && uv pip install --no-deps /tmp/nixl_wheels/nixl*.whl \ |
| 237 | && uv pip install --no-deps nixl==${NIXL_VERSION} \ |
| 238 | && rm -rf /tmp/nixl_wheels |
| 239 | |
| 240 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 241 | --mount=type=bind,src=requirements/common.txt,target=/workspace/vllm/requirements/common.txt \ |
| 242 | --mount=type=bind,src=requirements/xpu.txt,target=/workspace/vllm/requirements/xpu.txt \ |
| 243 | --mount=type=bind,src=requirements/test/xpu.txt,target=/workspace/vllm/requirements/test/xpu.txt \ |
| 244 | uv pip install grpcio-tools protobuf nanobind && \ |
| 245 | uv pip install -r /workspace/vllm/requirements/xpu.txt && \ |
| 246 | uv pip install --no-build-isolation -r /workspace/vllm/requirements/test/xpu.txt |
| 247 | |
| 248 | # Keep source-dependent layers near the end so frequent code-only changes |
| 249 | # don't invalidate heavy dependency and UCX/NIXL layers. |
| 250 | COPY . . |
| 251 | |
| 252 | # Drop the pre-built Rust artifacts into the source tree. setup.py detects |
| 253 | # them and ships them as-is, skipping the local Rust build. |
| 254 | COPY --from=rust-build /workspace/vllm/vllm-rs vllm/vllm-rs |
| 255 | COPY --from=rust-build /workspace/vllm/_rust_*.so vllm/ |
| 256 | |
| 257 | ARG GIT_REPO_CHECK=0 |
| 258 | RUN --mount=type=bind,source=.git,target=.git \ |
| 259 | if [ "$GIT_REPO_CHECK" != 0 ]; then bash tools/check_repo.sh; fi |
| 260 | |
| 261 | ENV VLLM_TARGET_DEVICE=xpu |
| 262 | ENV VLLM_WORKER_MULTIPROC_METHOD=spawn |
| 263 | |
| 264 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 265 | --mount=type=bind,source=.git,target=.git \ |
| 266 | uv pip install --no-build-isolation --no-deps . |
| 267 | |
| 268 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 269 | uv pip install -e tests/vllm_test_utils |
| 270 | |
| 271 | # Replace 2026.1.2 DLE packages to 2026.1.3 |
| 272 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 273 | --mount=type=bind,source=.git,target=.git \ |
| 274 | uv pip install \ |
| 275 | "intel-cmplr-lib-rt==2026.1.1" \ |
| 276 | "intel-cmplr-lib-ur==2026.1.1" \ |
| 277 | "intel-cmplr-lic-rt==2026.1.1" \ |
| 278 | "intel-sycl-rt==2026.1.1" \ |
| 279 | "oneccl-devel==2022.1.2; platform_system == 'Linux' and platform_machine == 'x86_64'" \ |
| 280 | "oneccl==2022.1.2; platform_system == 'Linux' and platform_machine == 'x86_64'" \ |
| 281 | "dpcpp-cpp-rt==2026.1.1" \ |
| 282 | "intel-opencl-rt==2026.1.1" \ |
| 283 | "intel-openmp==2026.1.1" \ |
| 284 | "intel-pti==1.1.0" |
| 285 | |
| 286 | ENTRYPOINT ["vllm", "serve"] |