main
rocm_gfx1250 742 lines 31.4 KB
Raw
1 # default base image
2 ARG REMOTE_VLLM="0"
3 ARG COMMON_WORKDIR=/app
4 ARG BASE_IMAGE=rocm/vllm-dev:base
5 ARG CI_BASE_IMAGE=rocm/vllm-dev:ci_base
6 # NIC backend for MoRI RDMA support.
7 # By default (all), drivers and userspace libraries for all supported NIC types
8 # (ainic and bnxt) are installed; MoRI selects the appropriate one at runtime.
9 # To install drivers for a single NIC type only, set NIC_BACKEND explicitly:
10 # --build-arg NIC_BACKEND=ainic # AMD AINIC (Pensando) only
11 # --build-arg NIC_BACKEND=bnxt # Broadcom Thor-2 only
12 # --build-arg NIC_BACKEND=none # Install nothing.
13 ARG NIC_BACKEND=all
14 # AMD AINIC apt repo settings
15 # Users can specify a custom version compatible with their host drivers.
16 # The default version has been tested with ionic-dkms=26.03.3.001
17 # (libionic1=54.0-187-1), required for MoRI-EP/NIXL on Pollara/AINIC.
18 ARG AINIC_VERSION=1.117.5-a-77
19 ARG UBUNTU_CODENAME=jammy
20
21 # Sccache configuration. Release builds use this today; CI can opt in when a
22 # shared S3-compatible cache backend is available.
23 ARG USE_SCCACHE
24 ARG SCCACHE_DOWNLOAD_URL
25 ARG SCCACHE_ENDPOINT
26 ARG SCCACHE_BUCKET_NAME=vllm-build-sccache
27 ARG SCCACHE_REGION_NAME=us-west-2
28 ARG SCCACHE_S3_NO_CREDENTIALS=0
29
30 FROM ${BASE_IMAGE} AS base
31
32 ARG ARG_PYTORCH_ROCM_ARCH=gfx1250
33 ENV PYTORCH_ROCM_ARCH=${ARG_PYTORCH_ROCM_ARCH:-${PYTORCH_ROCM_ARCH}}
34
35 # Install build dependencies and utilities
36 RUN apt-get update -q -y && apt-get install -q -y \
37 sqlite3 libsqlite3-dev libfmt-dev libmsgpack-dev libsuitesparse-dev \
38 apt-transport-https ca-certificates wget curl \
39 build-essential libnuma-dev ccache mold
40 RUN --mount=type=cache,target=/root/.cache/pip \
41 python3 -m pip install --upgrade pip
42 # Note: mold is installed but not set as the system default linker because
43 # some packages use JIT compilation at runtime with flags mold does not support.
44 # Build stages opt in via LDFLAGS="-fuse-ld=mold".
45 # Remove sccache only if not using sccache (it exists in base image from Dockerfile.rocm_base)
46 ARG USE_SCCACHE
47 RUN if [ "$USE_SCCACHE" != "1" ]; then \
48 apt-get purge -y sccache || true; \
49 python3 -m pip uninstall -y sccache || true; \
50 rm -f "$(which sccache)" || true; \
51 fi
52
53 # Install UV — download first, then run, so a curl failure is not masked by the pipe
54 RUN curl -LsSf --retry 3 --retry-delay 5 https://astral.sh/uv/install.sh -o /tmp/uv-install.sh \
55 && env UV_INSTALL_DIR="/usr/local/bin" sh /tmp/uv-install.sh \
56 && rm -f /tmp/uv-install.sh \
57 && uv --version
58
59 # This timeout (in seconds) is necessary when installing some dependencies via uv since it's likely to time out
60 # Reference: https://github.com/astral-sh/uv/pull/1694
61 ENV UV_HTTP_TIMEOUT=500
62 ENV UV_INDEX_STRATEGY="unsafe-best-match"
63 # Use copy mode to avoid hardlink failures with Docker cache mounts
64 ENV UV_LINK_MODE=copy
65 # python binary fall back for non venv builds
66 ENV UV_PYTHON=${VIRTUAL_ENV:-/usr}/bin/python3
67 # Expose paths from wheel installation
68 ENV PKG_CONFIG_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib/pkgconfig:${PKG_CONFIG_PATH}
69 # ccache directory - persisted across layer rebuilds via cache mounts.
70 ENV CCACHE_DIR=/root/.cache/ccache
71 ENV CCACHE_COMPILERCHECK=content
72 # Empty by default so build steps fall back to $(nproc); CI can override.
73 ARG max_jobs
74 ENV MAX_JOBS=${max_jobs}
75
76 # Install sccache if USE_SCCACHE is enabled (for release builds)
77 ARG USE_SCCACHE
78 ARG SCCACHE_DOWNLOAD_URL
79 ARG SCCACHE_ENDPOINT
80 ARG SCCACHE_BUCKET_NAME
81 ARG SCCACHE_REGION_NAME
82 ARG SCCACHE_S3_NO_CREDENTIALS
83 RUN if [ "$USE_SCCACHE" = "1" ]; then \
84 if command -v sccache >/dev/null 2>&1; then \
85 echo "sccache already installed, skipping installation"; \
86 sccache --version; \
87 else \
88 echo "Installing sccache..." \
89 && SCCACHE_ARCH="x86_64" \
90 && SCCACHE_VERSION="v0.8.1" \
91 && 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}" \
92 && curl -L -o /tmp/sccache.tar.gz ${SCCACHE_DL_URL} \
93 && tar -xzf /tmp/sccache.tar.gz -C /tmp \
94 && mv /tmp/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl/sccache /usr/bin/sccache \
95 && chmod +x /usr/bin/sccache \
96 && rm -rf /tmp/sccache.tar.gz /tmp/sccache-${SCCACHE_VERSION}-${SCCACHE_ARCH}-unknown-linux-musl \
97 && sccache --version; \
98 fi; \
99 fi
100
101 # Set sccache environment variables only when USE_SCCACHE=1
102 # This prevents S3 config from leaking into images when sccache is not used
103 ARG USE_SCCACHE
104 ENV SCCACHE_BUCKET=${USE_SCCACHE:+${SCCACHE_BUCKET_NAME}}
105 ENV SCCACHE_REGION=${USE_SCCACHE:+${SCCACHE_REGION_NAME}}
106 ENV SCCACHE_S3_NO_CREDENTIALS=${USE_SCCACHE:+${SCCACHE_S3_NO_CREDENTIALS}}
107 ENV SCCACHE_IDLE_TIMEOUT=${USE_SCCACHE:+0}
108
109 ARG COMMON_WORKDIR
110 WORKDIR ${COMMON_WORKDIR}
111
112
113 # -----------------------
114 # vLLM fetch stages
115 FROM base AS fetch_vllm_0
116 ONBUILD COPY ./ vllm/
117 FROM base AS fetch_vllm_1
118 ARG VLLM_REPO="https://github.com/ROCm/vllm.git"
119 ARG VLLM_BRANCH="455_wip"
120 ENV VLLM_REPO=${VLLM_REPO}
121 ENV VLLM_BRANCH=${VLLM_BRANCH}
122 ONBUILD RUN git clone ${VLLM_REPO} \
123 && cd vllm \
124 && git fetch -v --prune -- origin ${VLLM_BRANCH} \
125 && git checkout FETCH_HEAD \
126 && if [ ${VLLM_REPO} != "https://github.com/vllm-project/vllm.git" ] ; then \
127 git remote add upstream "https://github.com/vllm-project/vllm.git" \
128 && git fetch upstream ; fi
129 FROM fetch_vllm_${REMOTE_VLLM} AS fetch_vllm
130
131 # Resolve the device-independent source version once for every downstream
132 # artifact. setuptools-scm reads Git metadata from local and remote sources.
133 FROM fetch_vllm AS vllm-version
134 ARG COMMON_WORKDIR
135 RUN --mount=type=cache,id=vllm-rocm-uv,target=/root/.cache/uv \
136 cd ${COMMON_WORKDIR}/vllm \
137 && uv pip install --system -r requirements/build/rust.txt \
138 && python3 -c \
139 "from setuptools_scm import get_version; print(get_version(git_describe_command=['git', 'describe', '--dirty', '--tags', '--long', '--abbrev=40', '--match', 'v[0-9]*']))" \
140 > /vllm-version.txt
141
142 # -----------------------
143 # Rust build stage
144 # Builds the `vllm-rs` frontend in a dedicated stage so the wheel build stages
145 # don't need the rust toolchain.
146 FROM fetch_vllm AS rust-build
147 ARG COMMON_WORKDIR
148
149 # Cap cargo parallelism to avoid exhausting the AMD CI host's open-file limit
150 # (rustc spawns enough concurrent processes to hit RLIMIT_NOFILE otherwise).
151 ENV CARGO_BUILD_JOBS=4
152 ENV CARGO_NET_RETRY=10
153 ENV RUSTUP_MAX_RETRIES=10
154
155 RUN --mount=type=cache,id=vllm-rocm-uv,target=/root/.cache/uv \
156 cd ${COMMON_WORKDIR}/vllm \
157 && uv pip install --system -r requirements/build/rust.txt
158
159 COPY --from=vllm-version /vllm-version.txt /tmp/vllm-version.txt
160
161 # Build the release binary. Cargo's registry/git caches can be written by
162 # concurrent BuildKit jobs on shared workers, so lock those cache mounts while
163 # keeping the cache benefit. Do not cache target/, because stale target metadata
164 # can outlive source updates across BuildKit cache reuse.
165 RUN --mount=type=cache,id=vllm-rocm-cargo-registry,target=/root/.cargo/registry,sharing=locked \
166 --mount=type=cache,id=vllm-rocm-cargo-git,target=/root/.cargo/git,sharing=locked \
167 cd ${COMMON_WORKDIR}/vllm \
168 && export SETUPTOOLS_SCM_PRETEND_VERSION="$(cat /tmp/vllm-version.txt)" \
169 && bash tools/build_rust.sh \
170 && test -x vllm/vllm-rs
171
172 # -----------------------
173 # vLLM native build stages
174 #
175 # csrc-build intentionally copies only files that affect ROCm native extension
176 # compilation. That keeps unrelated CI/test/docs edits from invalidating the
177 # expensive HIP/C++ build layer.
178 FROM base AS csrc-build
179 ARG COMMON_WORKDIR
180 WORKDIR ${COMMON_WORKDIR}/vllm
181
182 COPY requirements/rocm.txt requirements/rocm.txt
183 COPY requirements/common.txt requirements/common.txt
184 RUN --mount=type=cache,id=vllm-rocm-uv,target=/root/.cache/uv \
185 uv pip install --system -r requirements/rocm.txt
186
187 # pyproject.toml is bind-mounted in the RUN step so metadata-only changes do
188 # not invalidate the expensive native build layer.
189 COPY setup.py CMakeLists.txt ./
190 COPY tools/build_rust.py tools/build_rust.py
191 COPY cmake cmake/
192 COPY csrc csrc/
193 COPY vllm/envs.py vllm/envs.py
194 COPY vllm/__init__.py vllm/__init__.py
195
196 ENV VLLM_TARGET_DEVICE=rocm
197 ENV SETUPTOOLS_SCM_PRETEND_VERSION="0.0.0+rocm.csrc.build"
198
199 RUN --mount=type=bind,source=pyproject.toml,target=${COMMON_WORKDIR}/vllm/pyproject.toml \
200 --mount=type=cache,id=vllm-rocm-ccache,target=/root/.cache/ccache \
201 export CCACHE_BASEDIR="$PWD" \
202 && echo "=== ccache stats before ROCm native build ===" \
203 && (ccache --show-stats || true) \
204 && (ccache --zero-stats || true) \
205 && EFFECTIVE_MAX_JOBS="${MAX_JOBS:-$(nproc)}" \
206 && echo "Building ROCm native extension wheel with MAX_JOBS=${EFFECTIVE_MAX_JOBS}" \
207 && LDFLAGS="-fuse-ld=mold" MAX_JOBS="${EFFECTIVE_MAX_JOBS}" python3 setup.py bdist_wheel --dist-dir=dist \
208 && test -d dist \
209 && ls dist/*.whl >/dev/null \
210 && echo "=== ccache stats after ROCm native build ===" \
211 && (ccache --show-stats || true)
212
213 # Build the full vLLM ROCm wheel by reusing the native extension wheel from
214 # csrc-build. This stage still rebuilds for Python/package changes, but skips
215 # the expensive HIP/C++ compile when native inputs are unchanged.
216 FROM fetch_vllm AS build_vllm
217 ARG COMMON_WORKDIR
218 ENV VLLM_TARGET_DEVICE=rocm
219
220 COPY --from=csrc-build ${COMMON_WORKDIR}/vllm/dist /precompiled-wheels
221 COPY --from=vllm-version /vllm-version.txt /tmp/vllm-version.txt
222
223 # Drop the pre-built Rust artifacts into the source tree. setup.py detects
224 # them and ships them as-is, skipping the local Rust build.
225 COPY --from=rust-build ${COMMON_WORKDIR}/vllm/vllm/vllm-rs ${COMMON_WORKDIR}/vllm/vllm/vllm-rs
226 COPY --from=rust-build ${COMMON_WORKDIR}/vllm/vllm/_rust_*.so ${COMMON_WORKDIR}/vllm/vllm/
227
228 RUN --mount=type=cache,id=vllm-rocm-uv,target=/root/.cache/uv \
229 cd vllm \
230 && uv pip install --system -r requirements/rocm.txt \
231 && export SETUPTOOLS_SCM_PRETEND_VERSION="$(cat /tmp/vllm-version.txt)" \
232 && export VLLM_USE_PRECOMPILED=1 \
233 && export VLLM_PRECOMPILED_WHEEL_LOCATION="$(ls /precompiled-wheels/*.whl)" \
234 && export VLLM_DOCKER_BUILD_CONTEXT=1 \
235 && echo "Packaging vLLM ROCm wheel using precompiled extensions from ${VLLM_PRECOMPILED_WHEEL_LOCATION}" \
236 && python3 setup.py bdist_wheel --dist-dir=dist \
237 && test -d dist \
238 && ls dist/*.whl >/dev/null
239 FROM scratch AS export_vllm
240 ARG COMMON_WORKDIR
241 COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/dist/*.whl /
242 COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/requirements /requirements
243 COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/benchmarks /benchmarks
244 COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/tests /tests
245 COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/examples /examples
246 COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/tools/install_torchcodec_rocm.sh /tools/install_torchcodec_rocm.sh
247 COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/docker/Dockerfile.rocm /docker/
248 COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/.buildkite /.buildkite
249 COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/pyproject.toml /pyproject.toml
250 COPY --from=build_vllm ${COMMON_WORKDIR}/vllm/vllm/v1 /vllm_v1
251
252 # RIXL/UCX build stages
253 FROM base AS build_rixl
254 ARG RIXL_BRANCH="39be1de8"
255 ARG RIXL_REPO="https://github.com/ROCm/RIXL.git"
256 ARG UCX_BRANCH="bfb51733"
257 ARG UCX_REPO="https://github.com/openucx/ucx.git"
258 # ENV ROCM_PATH=/opt/rocm -> correct ROCM_PATH is set in base image
259 ENV UCX_HOME=/usr/local/ucx
260 ENV RIXL_HOME=/usr/local/rixl
261 ENV RIXL_BENCH_HOME=/usr/local/rixl_bench
262
263 # RIXL build system dependences and RDMA support
264 RUN apt-get -y update && apt-get -y install autoconf libtool pkg-config \
265 libgrpc-dev \
266 libgrpc++-dev \
267 libprotobuf-dev \
268 protobuf-compiler-grpc \
269 libcpprest-dev \
270 libaio-dev \
271 librdmacm1 \
272 librdmacm-dev \
273 libibverbs1 \
274 libibverbs-dev \
275 ibverbs-utils \
276 rdmacm-utils \
277 ibverbs-providers \
278 && rm -rf /var/lib/apt/lists/*
279
280 RUN --mount=type=cache,target=/root/.cache/uv \
281 uv pip install --system meson auditwheel patchelf tomlkit
282
283 RUN --mount=type=cache,target=/root/.cache/ccache \
284 cd /usr/local/src && \
285 git clone ${UCX_REPO} && \
286 cd ucx && \
287 git checkout ${UCX_BRANCH} && \
288 ./autogen.sh && \
289 mkdir build && cd build && \
290 CC="ccache gcc" CXX="ccache g++" \
291 ../configure \
292 --prefix=/usr/local/ucx \
293 --enable-shared \
294 --disable-static \
295 --disable-doxygen-doc \
296 --enable-optimizations \
297 --enable-devel-headers \
298 --with-rocm=${ROCM_PATH} \
299 --with-verbs \
300 --with-dm \
301 --enable-mt && \
302 make -j$(nproc) && \
303 make install
304
305 ENV PATH=/usr/local/ucx/bin:$PATH
306 ENV LD_LIBRARY_PATH=${UCX_HOME}/lib:${LD_LIBRARY_PATH}
307
308 RUN --mount=type=cache,target=/root/.cache/ccache \
309 git clone ${RIXL_REPO} /opt/rixl && \
310 cd /opt/rixl && \
311 git checkout ${RIXL_BRANCH} && \
312 CC="ccache gcc" CXX="ccache g++" \
313 meson setup build --prefix=${RIXL_HOME} \
314 --force-fallback-for=abseil-cpp \
315 -Ducx_path=${UCX_HOME} \
316 -Drocm_path=${ROCM_PATH} && \
317 cd build && \
318 ninja -j$(nproc) && \
319 ninja install
320
321 # Generate RIXL wheel
322 # Exclude libcore and libpull from auditwheel: transitive dependencies
323 # that are not shipped in the wheel and vary across base images.
324 RUN cd /opt/rixl && \
325 sed -i "s/--exclude 'libamdhip64\*'/--exclude 'libamdhip64*' --exclude 'libcore*' --exclude 'libpull*'/" \
326 contrib/build-wheel.sh && \
327 # The wheel build re-runs meson via meson-python; force the bundled abseil
328 sed -i 's|setup = \["-Dinstall_headers=false"\]|setup = ["-Dinstall_headers=false", "--force-fallback-for=abseil-cpp"]|' \
329 pyproject.toml && \
330 grep -q 'force-fallback-for' pyproject.toml && \
331 mkdir -p /app/install && \
332 _ucx_install_dir=${UCX_HOME} \
333 ./contrib/build-wheel.sh \
334 --output-dir /app/install \
335 --rocm-dir ${ROCM_PATH} \
336 --ucx-plugins-dir ${UCX_HOME}/lib/ucx \
337 --nixl-plugins-dir ${RIXL_HOME}/lib/x86_64-linux-gnu/plugins
338
339 # ROCShmem build stage - split from DeepEP so changing DEEPEP_BRANCH does not
340 # invalidate the slow ROCShmem build.
341 FROM base AS build_rocshmem
342 ARG ROCSHMEM_BRANCH="f0acb0c6"
343 ARG ROCSHMEM_REPO="https://github.com/ROCm/rocm-systems.git"
344 # DeepEP only supports gfx942 and gfx950; build ROCShmem for the same set so
345 # it can be linked against DeepEP without arch mismatches.
346 ARG DEEPEP_ROCM_ARCH="gfx942;gfx950"
347 # ENV ROCM_PATH=/opt/rocm -> Correct rocm_path is set in base image
348 ENV ROCSHMEM_DIR=/opt/rocshmem
349
350 RUN --mount=type=cache,target=/root/.cache/ccache \
351 git clone --no-checkout --filter=blob:none ${ROCSHMEM_REPO} \
352 && cd rocm-systems \
353 && git sparse-checkout set --cone projects/rocshmem \
354 && git checkout ${ROCSHMEM_BRANCH} \
355 && mkdir -p projects/rocshmem/build \
356 && cd projects/rocshmem/build \
357 && CC="ccache gcc" CXX="ccache g++" INSTALL_PREFIX=${ROCSHMEM_DIR} \
358 bash ../scripts/build_configs/all_backends \
359 -DROCM_PATH=${ROCM_PATH} \
360 -DGPU_TARGETS="${DEEPEP_ROCM_ARCH}" \
361 -DUSE_EXTERNAL_MPI=OFF
362
363 # DeepEP build stage - depends on ROCShmem, builds the HIP kernel wheel.
364 FROM build_rocshmem AS build_deepep
365 ARG DEEPEP_BRANCH="a9ea9774"
366 ARG DEEPEP_REPO="https://github.com/ROCm/DeepEP.git"
367 ARG DEEPEP_NIC="cx7"
368
369 # Build DeepEP wheel. DeepEP looks for rocshmem at ROCSHMEM_DIR.
370 # DeepEP only supports gfx942 and gfx950, so avoid gfx90a in the default list.
371 RUN --mount=type=cache,target=/root/.cache/ccache \
372 export PYTORCH_ROCM_ARCH="gfx942;gfx950" \
373 && git clone ${DEEPEP_REPO} \
374 && cd DeepEP \
375 && git checkout ${DEEPEP_BRANCH} \
376 && 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
377
378 # MoRI runtime dependencies live in Dockerfile.rocm so NIC backend changes do
379 # not force users to rebuild the long-lived Dockerfile.rocm_base image.
380 FROM base AS mori_base
381 ARG NIC_BACKEND
382 ARG AINIC_VERSION
383 ARG UBUNTU_CODENAME
384 RUN /bin/bash -lc 'set -euo pipefail; \
385 \
386 install_ainic() { \
387 apt-get update && apt-get install -y --no-install-recommends ca-certificates curl gnupg apt-transport-https; \
388 rm -rf /var/lib/apt/lists/*; \
389 mkdir -p /etc/apt/keyrings; \
390 curl -fsSL https://repo.radeon.com/rocm/rocm.gpg.key | gpg --dearmor > /etc/apt/keyrings/amdainic.gpg; \
391 echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/amdainic.gpg] https://repo.radeon.com/amdainic/pensando/ubuntu/${AINIC_VERSION} ${UBUNTU_CODENAME} main" \
392 > /etc/apt/sources.list.d/amdainic.list; \
393 apt-get update && apt-get install -y --no-install-recommends \
394 libionic-dev \
395 ionic-common \
396 ; \
397 rm -rf /var/lib/apt/lists/*; \
398 }; \
399 \
400 # NOTE: requires FW 235.2.86.0 and kernel drivers on the host: \
401 # bnxt-en-dkms=1.10.3.235.2.86.0 bnxt-re-dkms=235.2.86.0 (from packages.broadcom.com PPA) \
402 install_bnxt() { \
403 install -m 0755 -d /etc/apt/keyrings; \
404 curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/PackagesKey/public \
405 -o /etc/apt/keyrings/broadcom-nic.asc; \
406 chmod a+r /etc/apt/keyrings/broadcom-nic.asc; \
407 echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/broadcom-nic.asc] https://packages.broadcom.com/artifactory/ethernet-nic-debian-public jammy main" \
408 > /etc/apt/sources.list.d/broadcom-nic.list; \
409 apt-get update && apt-get install -y --no-install-recommends \
410 bnxt-rocelib=235.2.86.0 \
411 ; \
412 cp -a /usr/local/lib/x86_64-linux-gnu/libbnxt_re* /usr/local/lib/; \
413 ldconfig; \
414 rm -rf /var/lib/apt/lists/*; \
415 }; \
416 \
417 echo "[MORI] Install MoRI proxy deps"; \
418 pip install --quiet --ignore-installed blinker && \
419 pip install --quiet quart msgpack aiohttp pyzmq; \
420 echo "[MORI] NIC_BACKEND=${NIC_BACKEND}"; \
421 \
422 # NIC backend deps — mori auto-detects NIC at runtime (MORI_DEVICE_NIC env var override). \
423 # Only vendor packages are installed here for dlopen; no compile-time flags needed. \
424 case "${NIC_BACKEND}" in \
425 none) ;; \
426 all) install_ainic; install_bnxt ;; \
427 ainic) install_ainic ;; \
428 bnxt) install_bnxt ;; \
429 *) echo "ERROR: unknown NIC_BACKEND=${NIC_BACKEND}. Use one of: none, ainic, bnxt, all"; exit 2 ;; \
430 esac'
431
432 # -----------------------
433 # vLLM wheel release build stage (for building distributable wheels)
434 # This stage pins dependencies to custom ROCm wheel versions and handles version detection
435 FROM fetch_vllm AS build_vllm_wheel_release
436
437 ARG COMMON_WORKDIR
438 COPY --from=vllm-version /vllm-version.txt /tmp/vllm-version.txt
439
440 # Drop the pre-built Rust artifacts into the source tree. setup.py detects
441 # them and ships them as-is, skipping the local Rust build.
442 COPY --from=rust-build ${COMMON_WORKDIR}/vllm/vllm/vllm-rs ${COMMON_WORKDIR}/vllm/vllm/vllm-rs
443 COPY --from=rust-build ${COMMON_WORKDIR}/vllm/vllm/_rust_*.so ${COMMON_WORKDIR}/vllm/vllm/
444
445 # Create /install directory for custom wheels
446 RUN mkdir -p /install
447
448 # Copy custom ROCm wheels from docker/context if they exist
449 # COPY ensures Docker cache is invalidated when wheels change
450 # .keep file ensures directory always exists for COPY to work
451 COPY docker/context/base-wheels/ /tmp/base-wheels/
452 # This is how we know if we are building for a wheel release or not.
453 # If there are not wheels found there, we are not building for a wheel release.
454 # So we exit with an error. To skip this stage.
455 RUN if [ -n "$(ls /tmp/base-wheels/*.whl 2>/dev/null)" ]; then \
456 echo "Found custom wheels - copying to /install"; \
457 cp /tmp/base-wheels/*.whl /install/ && \
458 echo "Copied custom wheels:"; \
459 ls -lh /install/; \
460 else \
461 echo "ERROR: No custom wheels found in docker/context/base-wheels/"; \
462 echo "Wheel releases require pre-built ROCm wheels."; \
463 exit 1; \
464 fi
465
466 # GIT_REPO_CHECK: Verify repo is clean and tags are available (for release builds)
467 # This matches CUDA's Dockerfile behavior for proper version detection via setuptools_scm
468 ARG GIT_REPO_CHECK=0
469 RUN if [ "$GIT_REPO_CHECK" != "0" ]; then \
470 echo "Running repository checks..."; \
471 cd vllm && bash tools/check_repo.sh; \
472 fi
473
474 # Install the packaging helpers before modifying requirements/rocm.txt.
475 RUN --mount=type=cache,target=/root/.cache/uv \
476 cd vllm \
477 && uv pip install --system setuptools_scm regex
478
479 # Fail if git-based package dependencies are found in requirements files
480 # (uv doesn't handle git+ URLs well, and packages should be distributed on PyPI)
481 # Extra notes: pip install is able to handle git+ URLs, but uv doesn't.
482 RUN echo "Checking for git-based packages in requirements files..." \
483 && echo "Checking common.txt for git-based packages:" \
484 && if grep -q 'git+' ${COMMON_WORKDIR}/vllm/requirements/common.txt; then \
485 echo "ERROR: Git-based packages found in common.txt:"; \
486 grep 'git+' ${COMMON_WORKDIR}/vllm/requirements/common.txt; \
487 echo "Please publish these packages to PyPI instead of using git dependencies."; \
488 exit 1; \
489 else \
490 echo " ✓ No git-based packages found in common.txt"; \
491 fi \
492 && echo "Checking rocm.txt for git-based packages:" \
493 && if grep -q 'git+' ${COMMON_WORKDIR}/vllm/requirements/rocm.txt; then \
494 echo "ERROR: Git-based packages found in rocm.txt:"; \
495 grep 'git+' ${COMMON_WORKDIR}/vllm/requirements/rocm.txt; \
496 echo "Please publish these packages to PyPI instead of using git dependencies."; \
497 exit 1; \
498 else \
499 echo " ✓ No git-based packages found in rocm.txt"; \
500 fi \
501 && echo "All requirements files are clean - no git-based packages found"
502
503 # Pin vLLM dependencies to exact versions of custom ROCm wheels
504 # This ensures 'pip install vllm' automatically installs correct torch/triton/torchvision/amdsmi
505 COPY tools/vllm-rocm/pin_rocm_dependencies.py /tmp/pin_rocm_dependencies.py
506 RUN echo "Pinning vLLM dependencies to custom wheel versions..." \
507 && python3 /tmp/pin_rocm_dependencies.py /install ${COMMON_WORKDIR}/vllm/requirements/rocm.txt
508
509 # Install dependencies using custom wheels from /install
510 RUN --mount=type=cache,target=/root/.cache/uv \
511 cd vllm \
512 && echo "Building vLLM with custom wheels from /install" \
513 && uv pip install --system --find-links /install -r requirements/rocm.txt
514
515 # Build wheel using the shared source version to avoid dirty state from modified requirements/rocm.txt
516 # (setup.py auto-detects ccache/sccache in PATH)
517 RUN --mount=type=cache,id=vllm-rocm-ccache,target=/root/.cache/ccache \
518 cd vllm \
519 && export CCACHE_BASEDIR="$PWD" \
520 && export SETUPTOOLS_SCM_PRETEND_VERSION="$(cat /tmp/vllm-version.txt)" \
521 && echo "Building wheel with version: ${SETUPTOOLS_SCM_PRETEND_VERSION}" \
522 && MAX_JOBS="${MAX_JOBS:-$(nproc)}" python3 setup.py bdist_wheel --dist-dir=dist
523
524 FROM scratch AS export_vllm_wheel_release
525 ARG COMMON_WORKDIR
526 COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/dist/*.whl /
527 COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/requirements /requirements
528 COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/benchmarks /benchmarks
529 COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/tests /tests
530 COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/examples /examples
531 COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/tools/install_torchcodec_rocm.sh /tools/install_torchcodec_rocm.sh
532 COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/docker/Dockerfile.rocm /docker/
533 COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/.buildkite /.buildkite
534 COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/pyproject.toml /pyproject.toml
535 COPY --from=build_vllm_wheel_release ${COMMON_WORKDIR}/vllm/vllm/v1 /vllm_v1
536
537 # -----------------------
538 # CI base image (Tier 1) - stable, rarely changing CI dependencies.
539 # Per-PR test builds pull this as CI_BASE_IMAGE so the test stage only layers
540 # in the vLLM artifacts for the current commit.
541 FROM mori_base AS ci_base
542 ARG COMMON_WORKDIR
543
544 # Update rdma-core to support latest rocshmem.
545 ARG DEEPEP_NIC
546 RUN if [ "${DEEPEP_NIC}" = "cx7" ] || [ "${DEEPEP_NIC}" = "io" ]; then \
547 git clone --branch v62.0 --depth 1 https://github.com/linux-rdma/rdma-core.git /tmp/rdma-core && \
548 cd /tmp/rdma-core && \
549 mkdir -p build && cd build && \
550 cmake -GNinja -DCMAKE_INSTALL_PREFIX=/usr -DNO_MAN_PAGES=1 .. && \
551 ninja && ninja install && ldconfig && rm -rf /tmp/rdma-core; \
552 fi
553
554 # Install RIXL + DeepEP wheels.
555 RUN --mount=type=bind,from=build_rixl,src=/app/install,target=/rixl_install \
556 --mount=type=bind,from=build_deepep,src=/app/deep_install,target=/deep_install \
557 uv pip install --system /rixl_install/*.whl /deep_install/*.whl
558
559 # Copy ROCShmem runtime libraries.
560 COPY --from=build_rocshmem /opt/rocshmem /opt/rocshmem
561
562 # RDMA userspace libraries plus FFmpeg dev libs needed by torchcodec.
563 RUN timeout --kill-after=30s 5m apt-get update -q -y --error-on=any \
564 -o Acquire::Retries=3 \
565 -o Acquire::http::Timeout=30 \
566 -o Acquire::https::Timeout=30 \
567 && apt-get install -q -y --no-install-recommends \
568 -o Acquire::Retries=3 \
569 -o Acquire::http::Timeout=30 \
570 -o Acquire::https::Timeout=30 \
571 librdmacm1 \
572 libibverbs1 \
573 ibverbs-providers \
574 ibverbs-utils \
575 libsodium23 \
576 pkg-config ffmpeg libavcodec-dev libavformat-dev libavutil-dev \
577 libswscale-dev libavdevice-dev libavfilter-dev libswresample-dev \
578 && rm -rf /var/lib/apt/lists/*
579
580 # Install torchcodec from source for ROCm/torch ABI compatibility.
581 COPY tools/install_torchcodec_rocm.sh /tmp/install_torchcodec.sh
582 RUN --mount=type=cache,target=/root/.cache/uv \
583 --mount=type=cache,target=/root/.cache/pip \
584 --mount=type=cache,target=/root/.cache/torchcodec-wheels \
585 bash /tmp/install_torchcodec.sh \
586 && rm /tmp/install_torchcodec.sh \
587 && apt-get clean && rm -rf /var/lib/apt/lists/*
588
589 # Pre-install shared ROCm runtime dependencies.
590 COPY requirements/common.txt requirements/rocm.txt /tmp/ci-base-requirements/
591 RUN --mount=type=cache,target=/root/.cache/uv \
592 uv pip install --system -r /tmp/ci-base-requirements/rocm.txt \
593 && rm -rf /tmp/ci-base-requirements
594
595 # Enable fast and less brittle model downloads in tests.
596 ENV HF_XET_HIGH_PERFORMANCE=1
597 ENV HF_HUB_DOWNLOAD_TIMEOUT=60
598
599 # Pre-install vLLM test dependencies.
600 COPY requirements/test/rocm.txt /tmp/rocm-test-reqs.txt
601 RUN --mount=type=cache,target=/root/.cache/uv \
602 uv pip install --system -r /tmp/rocm-test-reqs.txt
603
604 # Rebuild fastsafetensors from source so its C++ extension is compiled with
605 # USE_ROCM and can detect libamdhip64.so at runtime.
606 RUN --mount=type=cache,target=/root/.cache/pip \
607 FASTSAFETENSORS_REQ="$(grep -E '^fastsafetensors(==| @ )' /tmp/rocm-test-reqs.txt | head -1)" \
608 && test -n "${FASTSAFETENSORS_REQ}" \
609 && python3 -m pip install --force-reinstall --no-deps \
610 --no-binary fastsafetensors "${FASTSAFETENSORS_REQ}" \
611 && rm /tmp/rocm-test-reqs.txt
612
613 # Set MIOPEN ENVS to resolve performance regressions in MIOpen 3D convolution kernel.
614 # See: https://github.com/pytorch/pytorch/issues/169857
615 ENV MIOPEN_DEBUG_CONV_DIRECT=0
616 ENV MIOPEN_DEBUG_CONV_GEMM=0
617
618 # Use legacy IPC mode for HSA to avoid GPU memory pinning issues with UCX rocm_ipc.
619 # See: https://github.com/ROCm/rocm-libraries/issues/6266
620 ENV HSA_ENABLE_IPC_MODE_LEGACY=1
621
622 # ROCm profiler limits workaround.
623 RUN echo "ROCTRACER_MAX_EVENTS=10000000" > ${COMMON_WORKDIR}/libkineto.conf
624 ENV KINETO_CONFIG="${COMMON_WORKDIR}/libkineto.conf"
625
626 # Install vllm_test_utils in ci_base for ci_base + wheel parity.
627 COPY tests/vllm_test_utils /tmp/vllm_test_utils
628 RUN --mount=type=cache,target=/root/.cache/uv \
629 uv pip install --system /tmp/vllm_test_utils \
630 && rm -rf /tmp/vllm_test_utils
631
632 # -----------------------
633 # Test vLLM image (Tier 2) - vLLM-only layer on top of ci_base.
634 FROM ${CI_BASE_IMAGE} AS test
635 ARG COMMON_WORKDIR
636
637 # Install the vLLM wheel (--no-deps: all deps already in ci_base).
638 RUN --mount=type=bind,from=export_vllm,src=/,target=/install \
639 --mount=type=cache,target=/root/.cache/uv \
640 cd /install \
641 && uv pip install --system --no-deps *.whl
642
643 # Store the vLLM wheel in the image for python-only install tests.
644 COPY --from=export_vllm /*.whl /opt/vllm-wheels/
645
646 WORKDIR /vllm-workspace
647 COPY --from=build_vllm ${COMMON_WORKDIR}/vllm /vllm-workspace
648
649 # Copy in the v1 package (for python-only install test group).
650 COPY --from=export_vllm /vllm_v1 /usr/local/lib/python${PYTHON_VERSION}/dist-packages/vllm/v1
651
652 # Hide source under src/ so it won't shadow the installed package in tests.
653 RUN mkdir src && mv vllm src/vllm
654
655 # -----------------------
656 # Final vLLM image
657 FROM mori_base AS final
658 ENV UV_COMPILE_BYTECODE=1
659
660 RUN python3 -m pip install --upgrade pip && rm -rf /var/lib/apt/lists/*
661
662 # Clean up sccache from release image (not needed at runtime)
663 # This removes the binary and wrappers that may have been installed during build
664 RUN rm -f /usr/bin/sccache || true \
665 && rm -rf /opt/sccache-wrappers || true
666
667 # Unset sccache environment variables for the release image
668 # This prevents S3 bucket config from leaking into production images
669 ENV SCCACHE_BUCKET=
670 ENV SCCACHE_REGION=
671 ENV SCCACHE_ENDPOINT=
672 ENV SCCACHE_S3_NO_CREDENTIALS=
673 ENV SCCACHE_IDLE_TIMEOUT=
674
675 # Error related to odd state for numpy 1.20.3 where there is no METADATA etc, but an extra LICENSES_bundled.txt.
676 # Manually remove it so that later steps of numpy upgrade can continue
677 RUN case "$(which python3)" in \
678 *"/opt/conda/envs/py_3.9"*) \
679 rm -rf /opt/conda/envs/py_3.9/lib/python3.9/site-packages/numpy-1.20.3.dist-info/;; \
680 *) ;; esac
681
682 RUN --mount=type=cache,target=/root/.cache/uv \
683 uv pip install --system --upgrade huggingface-hub
684
685 # Install vLLM using uv (inherited from base stage)
686 # Note: No -U flag to avoid upgrading PyTorch ROCm to CUDA version
687 RUN --mount=type=bind,from=export_vllm,src=/,target=/install \
688 --mount=type=cache,target=/root/.cache/uv \
689 cd /install \
690 && uv pip install --system -r requirements/rocm.txt \
691 && pip uninstall -y vllm \
692 && uv pip install --system *.whl
693
694 # Install RIXL wheel
695 RUN --mount=type=bind,from=build_rixl,src=/app/install,target=/rixl_install \
696 uv pip install --system /rixl_install/*.whl
697
698 ARG COMMON_WORKDIR
699 ARG BASE_IMAGE
700 ARG NIC_BACKEND
701 ARG AINIC_VERSION
702
703 # Copy over the benchmark scripts as well
704 COPY --from=export_vllm /benchmarks ${COMMON_WORKDIR}/vllm/benchmarks
705 COPY --from=export_vllm /examples ${COMMON_WORKDIR}/vllm/examples
706 COPY --from=export_vllm /docker ${COMMON_WORKDIR}/vllm/docker
707
708 # Use legacy IPC mode for HSA to avoid GPU memory pinning issues with UCX rocm_ipc
709 # See: https://github.com/ROCm/rocm-libraries/issues/6266
710 ENV HSA_ENABLE_IPC_MODE_LEGACY=1
711
712 ENV TOKENIZERS_PARALLELISM=false
713
714 # ENV that can improve safe tensor loading, and end-to-end time
715 ENV SAFETENSORS_FAST_GPU=1
716
717 # Performance environment variable.
718 ENV HIP_FORCE_DEV_KERNARG=1
719
720 # Workaround for ROCm profiler limits
721 RUN echo "ROCTRACER_MAX_EVENTS=10000000" > ${COMMON_WORKDIR}/libkineto.conf
722 ENV KINETO_CONFIG="${COMMON_WORKDIR}/libkineto.conf"
723 RUN echo "VLLM_BASE_IMAGE=${BASE_IMAGE}" >> ${COMMON_WORKDIR}/versions.txt \
724 && echo "MORI_NIC_BACKEND=${NIC_BACKEND}" >> ${COMMON_WORKDIR}/versions.txt \
725 && echo "AINIC_VERSION=${AINIC_VERSION}" >> ${COMMON_WORKDIR}/versions.txt
726
727 # Download bench scripts for gfx1250
728 RUN curl -k -O https://raw.githubusercontent.com/ROCm/vllm/refs/heads/gfx1250_bench/vllm_smoketest.sh
729
730
731 ### Install triton from upstream for AITER Deps TODO: (JPVILLAM) If possible to get this on whls it would be better
732 RUN pip3 uninstall -y triton && \
733 git clone https://github.com/triton-lang/triton.git && \
734 cd triton && \
735 git checkout c517f38c && \
736 TRITON_APPEND_CMAKE_ARGS="-DCMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH=FALSE" pip3 install .
737
738 CMD ["/bin/bash"]
739
740 #Set entrypoint for vllm-openai official images
741 FROM final AS vllm-openai
742 ENTRYPOINT ["vllm", "serve"]