| 1 | # This vLLM Dockerfile is used to build images that can run vLLM on both x86_64 and arm64 CPU platforms. |
| 2 | # |
| 3 | # Supported platforms: |
| 4 | # - linux/amd64 (x86_64) |
| 5 | # - linux/arm64 (aarch64) |
| 6 | # |
| 7 | # Use the `--platform` option with `docker buildx build` to specify the target architecture, e.g.: |
| 8 | # docker buildx build --platform=linux/arm64 -f docker/Dockerfile.cpu . |
| 9 | # |
| 10 | # Build targets: |
| 11 | # vllm-openai (default): used for serving deployment |
| 12 | # vllm-test: used for CI tests |
| 13 | # vllm-dev: used for development |
| 14 | # |
| 15 | # Build arguments: |
| 16 | # PYTHON_VERSION=3.13|3.12 (default)|3.11|3.10 |
| 17 | # VLLM_CPU_X86=false (default)|true (for cross-compilation) |
| 18 | # VLLM_CPU_ARM_BF16=false (default)|true (for cross-compilation) |
| 19 | # |
| 20 | |
| 21 | ######################### BASE IMAGE ######################### |
| 22 | # Common apt packages and the optional sccache binary install, shared by |
| 23 | # base-common and rust-build (the latter is deliberately not `FROM |
| 24 | # base-common`, to stay minimal and build in parallel with vllm-build). |
| 25 | # |
| 26 | # Optional remote (S3-backed) compiler cache. Local BuildKit `--mount=type=cache` |
| 27 | # cache mounts (ccache, cargo registry) aren't exported by `--cache-to |
| 28 | # type=registry`, so they don't survive a build landing on a different/fresh |
| 29 | # builder. sccache's cache lives in S3 instead, so it does. |
| 30 | FROM ubuntu:22.04 AS base |
| 31 | |
| 32 | RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ |
| 33 | --mount=type=cache,target=/var/lib/apt,sharing=locked \ |
| 34 | apt-get update -y \ |
| 35 | && apt-get install -y --no-install-recommends ca-certificates curl git |
| 36 | |
| 37 | ARG TARGETARCH |
| 38 | ARG USE_SCCACHE |
| 39 | ARG SCCACHE_DOWNLOAD_URL |
| 40 | |
| 41 | RUN if [ "$USE_SCCACHE" = "1" ]; then \ |
| 42 | echo "Installing sccache..." \ |
| 43 | && case "${TARGETARCH}" in \ |
| 44 | arm64) SCCACHE_ARCH="aarch64" ;; \ |
| 45 | amd64) SCCACHE_ARCH="x86_64" ;; \ |
| 46 | *) echo "Unsupported TARGETARCH for sccache: ${TARGETARCH}" >&2; exit 1 ;; \ |
| 47 | esac \ |
| 48 | && export SCCACHE_DOWNLOAD_URL="${SCCACHE_DOWNLOAD_URL:-https://github.com/mozilla/sccache/releases/download/v0.8.1/sccache-v0.8.1-${SCCACHE_ARCH}-unknown-linux-musl.tar.gz}" \ |
| 49 | && curl -L -o sccache.tar.gz "${SCCACHE_DOWNLOAD_URL}" \ |
| 50 | && tar -xzf sccache.tar.gz \ |
| 51 | && mv sccache-v0.8.1-${SCCACHE_ARCH}-unknown-linux-musl/sccache /usr/bin/sccache \ |
| 52 | && rm -rf sccache.tar.gz sccache-v0.8.1-${SCCACHE_ARCH}-unknown-linux-musl; \ |
| 53 | fi |
| 54 | |
| 55 | ######################### BINUTILS BUILD IMAGE ######################### |
| 56 | # Build a newer GNU assembler for the AMX-FP8 instruction set. |
| 57 | FROM base AS binutils-build |
| 58 | |
| 59 | ARG BINUTILS_VERSION=2.47 |
| 60 | |
| 61 | RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ |
| 62 | --mount=type=cache,target=/var/lib/apt,sharing=locked \ |
| 63 | apt-get update -y \ |
| 64 | && apt-get install -y --no-install-recommends \ |
| 65 | bison \ |
| 66 | build-essential \ |
| 67 | flex \ |
| 68 | texinfo \ |
| 69 | xz-utils \ |
| 70 | && curl -fsSLO "https://sourceware.org/pub/binutils/releases/binutils-${BINUTILS_VERSION}.tar.xz" \ |
| 71 | && tar -xf "binutils-${BINUTILS_VERSION}.tar.xz" \ |
| 72 | && mkdir binutils-build \ |
| 73 | && cd binutils-build \ |
| 74 | && "../binutils-${BINUTILS_VERSION}/configure" --prefix=/opt/binutils --disable-nls --disable-werror \ |
| 75 | && make -j"$(nproc)" \ |
| 76 | && make install \ |
| 77 | && cd .. \ |
| 78 | && rm -rf binutils-build "/binutils-${BINUTILS_VERSION}" "binutils-${BINUTILS_VERSION}.tar.xz" |
| 79 | |
| 80 | ######################### COMMON BASE IMAGE ######################### |
| 81 | FROM base AS base-common |
| 82 | |
| 83 | WORKDIR /workspace |
| 84 | |
| 85 | COPY --from=binutils-build /opt/binutils /opt/binutils |
| 86 | |
| 87 | ARG PYTHON_VERSION=3.12 |
| 88 | |
| 89 | ARG max_jobs=32 |
| 90 | ENV MAX_JOBS=${max_jobs} |
| 91 | |
| 92 | # Install minimal dependencies and uv |
| 93 | RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ |
| 94 | --mount=type=cache,target=/var/lib/apt,sharing=locked \ |
| 95 | apt-get update -y \ |
| 96 | && apt-get install -y --no-install-recommends sudo ccache git curl wget ca-certificates zlib1g-dev \ |
| 97 | software-properties-common libtcmalloc-minimal4 libnuma-dev ffmpeg libsm6 libxext6 libgl1 jq lsof make xz-utils \ |
| 98 | && for i in 1 2 3; do \ |
| 99 | add-apt-repository -y ppa:ubuntu-toolchain-r/test && break || \ |
| 100 | { echo "Attempt $i failed, retrying toolchain PPA..."; sleep 5; }; \ |
| 101 | done \ |
| 102 | && apt-get update -y \ |
| 103 | && apt-get install -y --no-install-recommends gcc-15 g++-15 \ |
| 104 | && update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-15 10 --slave /usr/bin/g++ g++ /usr/bin/g++-15 \ |
| 105 | && curl -LsSf https://astral.sh/uv/install.sh | sh |
| 106 | |
| 107 | ARG TARGETARCH |
| 108 | ARG USE_SCCACHE |
| 109 | ARG SCCACHE_BUCKET_NAME=vllm-build-sccache |
| 110 | ARG SCCACHE_REGION_NAME=us-west-2 |
| 111 | ARG SCCACHE_S3_NO_CREDENTIALS=0 |
| 112 | |
| 113 | ENV SCCACHE_BUCKET=${USE_SCCACHE:+${SCCACHE_BUCKET_NAME}} |
| 114 | ENV SCCACHE_REGION=${USE_SCCACHE:+${SCCACHE_REGION_NAME}} |
| 115 | ENV SCCACHE_S3_NO_CREDENTIALS=${USE_SCCACHE:+${SCCACHE_S3_NO_CREDENTIALS}} |
| 116 | ENV SCCACHE_IDLE_TIMEOUT=${USE_SCCACHE:+0} |
| 117 | |
| 118 | # Compiler and linker environment |
| 119 | ENV CC=/usr/bin/gcc-15 CXX=/usr/bin/g++-15 |
| 120 | ENV CCACHE_DIR=/root/.cache/ccache |
| 121 | ENV CMAKE_CXX_COMPILER_LAUNCHER=ccache |
| 122 | |
| 123 | ENV PATH="/opt/binutils/bin:/root/.local/bin:$PATH" |
| 124 | ENV COMPILER_PATH="/opt/binutils/bin" |
| 125 | ENV VIRTUAL_ENV="/opt/venv" |
| 126 | ENV UV_PYTHON_INSTALL_DIR=/opt/uv/python |
| 127 | RUN uv venv --python ${PYTHON_VERSION} --seed ${VIRTUAL_ENV} |
| 128 | ENV PATH="$VIRTUAL_ENV/bin:$PATH" |
| 129 | |
| 130 | ENV UV_HTTP_TIMEOUT=500 |
| 131 | |
| 132 | # Install Python dependencies |
| 133 | ENV UV_INDEX_STRATEGY="unsafe-best-match" |
| 134 | ENV UV_LINK_MODE="copy" |
| 135 | |
| 136 | ENV TARGETARCH=${TARGETARCH} |
| 137 | |
| 138 | ######################### COMMON BASE IMAGE + PYTHON DEPS ######################### |
| 139 | FROM base-common AS base-common-pydeps |
| 140 | |
| 141 | ENV UV_COMPILE_BYTECODE=1 |
| 142 | |
| 143 | # PyTorch provides its own indexes for standard and nightly builds. |
| 144 | # PYTORCH_NIGHTLY=1 builds the CPU image against torch nightly (parity with the |
| 145 | # GPU torch-nightly lane); default 0 keeps the pinned release CPU build. |
| 146 | ARG PYTORCH_NIGHTLY=0 |
| 147 | ARG PYTORCH_CPU_INDEX_BASE_URL=https://download.pytorch.org/whl |
| 148 | |
| 149 | # Copy requirements files for installation |
| 150 | COPY requirements/common.txt requirements/common.txt |
| 151 | COPY requirements/cpu.txt requirements/cpu.txt |
| 152 | COPY tools/use_existing_torch.py tools/use_existing_torch.py |
| 153 | |
| 154 | # For nightly: install torch nightly (CPU) first, strip torch pins from the |
| 155 | # requirements via tools/use_existing_torch.py so they can't pull it back to a release |
| 156 | # build, then install the rest from the nightly CPU index (no --torch-backend, |
| 157 | # which would force the stable channel). Release path is unchanged. |
| 158 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 159 | uv pip install --upgrade pip && \ |
| 160 | if [ "${PYTORCH_NIGHTLY}" = "1" ]; then \ |
| 161 | echo "Installing torch nightly (CPU)..." \ |
| 162 | && uv pip install torch torchaudio torchvision torchcodec --pre \ |
| 163 | --index-url ${PYTORCH_CPU_INDEX_BASE_URL}/nightly/cpu \ |
| 164 | && python3 tools/use_existing_torch.py --prefix \ |
| 165 | && uv pip install -r requirements/cpu.txt \ |
| 166 | --extra-index-url ${PYTORCH_CPU_INDEX_BASE_URL}/nightly/cpu; \ |
| 167 | else \ |
| 168 | uv pip install -r requirements/cpu.txt --torch-backend cpu; \ |
| 169 | fi |
| 170 | |
| 171 | ######################### x86_64 BASE IMAGE ######################### |
| 172 | FROM base-common-pydeps AS base-amd64 |
| 173 | |
| 174 | ENV LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4:/opt/venv/lib/libiomp5.so" |
| 175 | |
| 176 | ######################### arm64 BASE IMAGE ######################### |
| 177 | FROM base-common-pydeps AS base-arm64 |
| 178 | |
| 179 | ENV LD_PRELOAD="/usr/lib/aarch64-linux-gnu/libtcmalloc_minimal.so.4" |
| 180 | |
| 181 | ######################### ARCH BASE IMAGE ######################### |
| 182 | FROM base-${TARGETARCH} AS base-arch |
| 183 | |
| 184 | RUN echo 'ulimit -c 0' >> ~/.bashrc |
| 185 | |
| 186 | ######################### RUST BUILD IMAGE ######################### |
| 187 | # Build the Rust frontend (`vllm-rs`) in a dedicated stage so the wheel build |
| 188 | # stage doesn't need the rust toolchain. This stage runs in parallel |
| 189 | # with the main vllm-build stage. |
| 190 | FROM base AS rust-build-cache |
| 191 | ENV DEBIAN_FRONTEND=noninteractive |
| 192 | |
| 193 | RUN apt-get update -y \ |
| 194 | && apt-get install -y --no-install-recommends \ |
| 195 | build-essential python3 python3-pip \ |
| 196 | && rm -rf /var/lib/apt/lists/* |
| 197 | |
| 198 | WORKDIR /workspace |
| 199 | |
| 200 | COPY requirements/build/rust.txt requirements/build/rust.txt |
| 201 | RUN python3 -m pip install --no-cache-dir -r requirements/build/rust.txt |
| 202 | |
| 203 | ARG USE_SCCACHE |
| 204 | ARG SCCACHE_ENDPOINT |
| 205 | ARG SCCACHE_BUCKET_NAME=vllm-build-sccache |
| 206 | ARG SCCACHE_REGION_NAME=us-west-2 |
| 207 | # When set, sccache skips the S3 backend and uses a local disk cache instead |
| 208 | # (for builds without S3 credentials, e.g. a developer's local `docker build`). |
| 209 | ARG SCCACHE_LOCAL_ONLY=0 |
| 210 | |
| 211 | ENV SCCACHE_BUCKET=${USE_SCCACHE:+${SCCACHE_BUCKET_NAME}} |
| 212 | ENV SCCACHE_REGION=${USE_SCCACHE:+${SCCACHE_REGION_NAME}} |
| 213 | # Avoid port collision with vllm-build's own sccache daemon. |
| 214 | ENV SCCACHE_SERVER_PORT=4227 |
| 215 | |
| 216 | # Copy only the Rust build inputs; tools/build_rust.sh publishes artifacts needed |
| 217 | # by the wheel build stage. |
| 218 | COPY rust rust |
| 219 | COPY rust-toolchain.toml rust-toolchain.toml |
| 220 | COPY tools/build_rust.py tools/build_rust.py |
| 221 | COPY tools/build_rust.sh tools/build_rust.sh |
| 222 | |
| 223 | # Cap cargo parallelism to avoid exhausting the CI host's open-file limit |
| 224 | # (rustc spawns enough concurrent processes to hit RLIMIT_NOFILE otherwise). |
| 225 | ENV CARGO_BUILD_JOBS=4 |
| 226 | |
| 227 | # Build with a stable version so this target snapshot is keyed only by Rust |
| 228 | # inputs. The child stage below relinks the crates that embed the exact version. |
| 229 | RUN --mount=type=cache,target=/root/.cargo/registry,sharing=locked \ |
| 230 | --mount=type=cache,target=/root/.cargo/git,sharing=locked \ |
| 231 | --mount=type=cache,target=/root/.cache/sccache-local,sharing=locked \ |
| 232 | --mount=type=secret,id=aws-credentials,target=/root/.aws/credentials,required=false \ |
| 233 | if [ "$USE_SCCACHE" = "1" ]; then \ |
| 234 | export RUSTC_WRAPPER=sccache; \ |
| 235 | if [ "$SCCACHE_LOCAL_ONLY" = "1" ]; then \ |
| 236 | unset SCCACHE_BUCKET SCCACHE_REGION; \ |
| 237 | export SCCACHE_DIR=/root/.cache/sccache-local SCCACHE_CACHE_SIZE=20G; \ |
| 238 | elif [ -n "${SCCACHE_ENDPOINT}" ]; then \ |
| 239 | export SCCACHE_ENDPOINT="${SCCACHE_ENDPOINT}"; \ |
| 240 | fi; \ |
| 241 | sccache --show-stats; \ |
| 242 | fi && \ |
| 243 | SETUPTOOLS_SCM_PRETEND_VERSION="0.0.0+docker.cache" bash tools/build_rust.sh && \ |
| 244 | if [ "$USE_SCCACHE" = "1" ]; then sccache --show-stats; fi |
| 245 | |
| 246 | # tools/build_rust.sh installed rustup here via rustup.rs; put it on PATH so the |
| 247 | # child stage below finds it on disk instead of re-downloading it. |
| 248 | ENV PATH="/root/.cargo/bin:${PATH}" |
| 249 | |
| 250 | # Relink with the exact Git-derived package version. |
| 251 | FROM rust-build-cache AS rust-build |
| 252 | |
| 253 | RUN --mount=type=cache,target=/root/.cargo/registry,sharing=locked \ |
| 254 | --mount=type=cache,target=/root/.cargo/git,sharing=locked \ |
| 255 | --mount=type=bind,source=.git,target=.git \ |
| 256 | SETUPTOOLS_SCM_PRETEND_METADATA="{dirty=false}" bash tools/build_rust.sh |
| 257 | |
| 258 | ######################### SOURCE PREP IMAGE ######################### |
| 259 | # Shared prep (source, rust artifacts, build deps) for both vllm-build and |
| 260 | # vllm-dev, so the two independent compiles (bdist_wheel vs. setup.py |
| 261 | # develop) can run concurrently instead of vllm-dev waiting on a wheel |
| 262 | # build it never uses. |
| 263 | FROM base-arch AS vllm-src |
| 264 | |
| 265 | # Re-declare torch-nightly args (ARGs do not cross FROM) |
| 266 | ARG PYTORCH_NIGHTLY=0 |
| 267 | ARG PYTORCH_CPU_INDEX_BASE_URL=https://download.pytorch.org/whl |
| 268 | |
| 269 | ARG GIT_REPO_CHECK=0 |
| 270 | # Support for cross-compilation with x86 ISA including AVX2 and AVX512: docker build --build-arg VLLM_CPU_X86="true" ... |
| 271 | ARG VLLM_CPU_X86=0 |
| 272 | ENV VLLM_CPU_X86=${VLLM_CPU_X86} |
| 273 | # Support for cross-compilation with ARM BF16 ISA: docker build --build-arg VLLM_CPU_ARM_BF16="true" ... |
| 274 | ARG VLLM_CPU_ARM_BF16=0 |
| 275 | ENV VLLM_CPU_ARM_BF16=${VLLM_CPU_ARM_BF16} |
| 276 | ARG ENABLE_AMX_FP8=1 |
| 277 | |
| 278 | WORKDIR /vllm-workspace |
| 279 | |
| 280 | # Validate build arguments - prevent mixing incompatible ISA flags |
| 281 | RUN if [ "$TARGETARCH" = "arm64" ] && [ "$VLLM_CPU_X86" != "0" ]; then \ |
| 282 | echo "ERROR: Cannot use x86-specific ISA flags (AVX2, AVX512, etc.) when building for ARM64 (--platform=linux/arm64)"; \ |
| 283 | exit 1; \ |
| 284 | fi && \ |
| 285 | if [ "$TARGETARCH" = "amd64" ] && [ "$VLLM_CPU_ARM_BF16" != "0" ]; then \ |
| 286 | echo "ERROR: Cannot use ARM-specific ISA flags (ARM_BF16) when building for x86_64 (--platform=linux/amd64)"; \ |
| 287 | exit 1; \ |
| 288 | fi |
| 289 | |
| 290 | # Copy build requirements |
| 291 | COPY requirements/build/cpu.txt requirements/build/cpu.txt |
| 292 | |
| 293 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 294 | if [ "${PYTORCH_NIGHTLY}" = "1" ]; then \ |
| 295 | python3 /workspace/tools/use_existing_torch.py --prefix \ |
| 296 | && uv pip install -r requirements/build/cpu.txt \ |
| 297 | --extra-index-url ${PYTORCH_CPU_INDEX_BASE_URL}/nightly/cpu; \ |
| 298 | else \ |
| 299 | uv pip install -r requirements/build/cpu.txt --torch-backend cpu; \ |
| 300 | fi |
| 301 | |
| 302 | COPY . . |
| 303 | |
| 304 | # Drop the pre-built Rust artifacts into the source tree. setup.py detects |
| 305 | # them and ships them as-is, skipping the local Rust build. |
| 306 | COPY --from=rust-build /workspace/vllm/vllm-rs vllm/vllm-rs |
| 307 | COPY --from=rust-build /workspace/vllm/_rust_*.so vllm/ |
| 308 | |
| 309 | RUN if [ "$GIT_REPO_CHECK" != 0 ]; then bash tools/check_repo.sh ; fi |
| 310 | |
| 311 | # For torch nightly, strip the torch/vision/audio/codec pins from the source |
| 312 | # tree's requirements *after* `COPY . .` (which restored the pinned files) so |
| 313 | # the wheel built below does not hard-pin the release torch (e.g. |
| 314 | # torch==2.11.0+cpu). setup.py reads requirements/cpu.txt into install_requires; |
| 315 | # leaving the pin makes `uv pip install dist/*.whl` unsatisfiable against the |
| 316 | # nightly index. The nightly torch installed in the base image satisfies the |
| 317 | # now-unpinned dependency. Done at the end of vllm-src so vllm-build and |
| 318 | # vllm-dev, which both derive from it, inherit the unpinned tree. |
| 319 | RUN if [ "${PYTORCH_NIGHTLY}" = "1" ]; then \ |
| 320 | python3 /workspace/tools/use_existing_torch.py --prefix; \ |
| 321 | fi |
| 322 | |
| 323 | ######################### BUILD IMAGE ######################### |
| 324 | FROM vllm-src AS vllm-build |
| 325 | |
| 326 | ARG USE_SCCACHE |
| 327 | ARG SCCACHE_ENDPOINT |
| 328 | ARG SCCACHE_LOCAL_ONLY=0 |
| 329 | |
| 330 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 331 | --mount=type=cache,target=/root/.cache/ccache \ |
| 332 | --mount=type=cache,target=/root/.cache/sccache-local,sharing=locked \ |
| 333 | --mount=type=cache,target=/vllm-workspace/.deps,sharing=locked \ |
| 334 | --mount=type=secret,id=aws-credentials,target=/root/.aws/credentials,required=false \ |
| 335 | if [ "$USE_SCCACHE" = "1" ]; then \ |
| 336 | if [ "$SCCACHE_LOCAL_ONLY" = "1" ]; then \ |
| 337 | unset SCCACHE_BUCKET SCCACHE_REGION; \ |
| 338 | export SCCACHE_DIR=/root/.cache/sccache-local SCCACHE_CACHE_SIZE=20G; \ |
| 339 | elif [ -n "${SCCACHE_ENDPOINT}" ]; then \ |
| 340 | export SCCACHE_ENDPOINT="${SCCACHE_ENDPOINT}"; \ |
| 341 | fi; \ |
| 342 | sccache --show-stats; \ |
| 343 | fi && \ |
| 344 | CMAKE_ARGS="-DENABLE_AMX_FP8=${ENABLE_AMX_FP8}" \ |
| 345 | VLLM_TARGET_DEVICE=cpu python3 setup.py bdist_wheel --dist-dir=dist --py-limited-api=cp38 && \ |
| 346 | if [ "$USE_SCCACHE" = "1" ]; then sccache --show-stats; fi |
| 347 | |
| 348 | ######################### TEST DEPS ######################### |
| 349 | FROM base-arch AS vllm-test-deps |
| 350 | |
| 351 | # Re-declare torch-nightly args (ARGs do not cross FROM) |
| 352 | ARG PYTORCH_NIGHTLY=0 |
| 353 | ARG PYTORCH_CPU_INDEX_BASE_URL=https://download.pytorch.org/whl |
| 354 | |
| 355 | WORKDIR /vllm-workspace |
| 356 | |
| 357 | # Test requirements are compiled from requirements/test/cuda.in into |
| 358 | # requirements/test/cpu.txt by the pip-compile-cpu pre-commit hook, which |
| 359 | # resolves CPU wheels via uv's --torch-backend cpu. |
| 360 | COPY requirements/test/cpu.txt requirements/test/cpu.txt |
| 361 | |
| 362 | # cpu.txt is compiled for x86_64, so platform markers are resolved away. Drop |
| 363 | # packages unavailable on aarch64 (decord, terratorch) for arm builds. Also |
| 364 | # drop the generic PyPI triton pulled in transitively (via xgrammar) on x86 |
| 365 | # builds, so it doesn't clobber the triton-cpu wheel from requirements/cpu.txt. |
| 366 | RUN case "$(uname -m)" in \ |
| 367 | aarch64|arm64) sed -i '/^decord==/d; /^terratorch==/d' requirements/test/cpu.txt ;; \ |
| 368 | x86_64) sed -i '/^triton==/d' requirements/test/cpu.txt ;; \ |
| 369 | esac |
| 370 | |
| 371 | # pytrec-eval-terrier bundles pre-C23 trec_eval sources. GCC 15 defaults to C23; |
| 372 | # use C17 for test dependency builds without changing the vLLM compiler flags. |
| 373 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 374 | export CFLAGS="${CFLAGS:+${CFLAGS} }-std=gnu17" && \ |
| 375 | if [ "${PYTORCH_NIGHTLY}" = "1" ]; then \ |
| 376 | python3 /workspace/tools/use_existing_torch.py --prefix \ |
| 377 | && uv pip install -r requirements/test/cpu.txt \ |
| 378 | --extra-index-url ${PYTORCH_CPU_INDEX_BASE_URL}/nightly/cpu; \ |
| 379 | else \ |
| 380 | uv pip install -r requirements/test/cpu.txt --torch-backend cpu; \ |
| 381 | fi |
| 382 | |
| 383 | ######################### DEV IMAGE ######################### |
| 384 | FROM vllm-src AS vllm-dev |
| 385 | |
| 386 | # Re-declare torch-nightly args (ARGs do not cross FROM) |
| 387 | ARG PYTORCH_NIGHTLY=0 |
| 388 | ARG PYTORCH_CPU_INDEX_BASE_URL=https://download.pytorch.org/whl |
| 389 | |
| 390 | WORKDIR /vllm-workspace |
| 391 | |
| 392 | RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ |
| 393 | --mount=type=cache,target=/var/lib/apt,sharing=locked \ |
| 394 | apt-get install -y --no-install-recommends vim numactl clangd-14 |
| 395 | |
| 396 | RUN ln -s /usr/bin/clangd-14 /usr/bin/clangd |
| 397 | |
| 398 | # install development dependencies (for testing) |
| 399 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 400 | uv pip install --no-build-isolation -e tests/vllm_test_utils |
| 401 | |
| 402 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 403 | --mount=type=cache,target=/root/.cache/ccache \ |
| 404 | --mount=type=bind,source=.git,target=.git \ |
| 405 | VLLM_TARGET_DEVICE=cpu python3 setup.py develop |
| 406 | |
| 407 | COPY --from=vllm-test-deps /vllm-workspace/requirements/test/cpu.txt requirements/test/cpu.txt |
| 408 | |
| 409 | # vllm-dev installs the same test dependencies in its own environment. |
| 410 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 411 | export CFLAGS="${CFLAGS:+${CFLAGS} }-std=gnu17" && \ |
| 412 | uv pip install -r requirements/lint.txt && \ |
| 413 | if [ "${PYTORCH_NIGHTLY}" = "1" ]; then \ |
| 414 | uv pip install -r requirements/test/cpu.txt \ |
| 415 | --extra-index-url ${PYTORCH_CPU_INDEX_BASE_URL}/nightly/cpu; \ |
| 416 | else \ |
| 417 | uv pip install -r requirements/test/cpu.txt --torch-backend cpu; \ |
| 418 | fi && \ |
| 419 | pre-commit install --hook-type pre-commit --hook-type commit-msg |
| 420 | |
| 421 | ENTRYPOINT ["bash"] |
| 422 | |
| 423 | ######################### TEST IMAGE ######################### |
| 424 | FROM vllm-test-deps AS vllm-test |
| 425 | |
| 426 | WORKDIR /vllm-workspace |
| 427 | |
| 428 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 429 | --mount=type=bind,from=vllm-build,src=/vllm-workspace/dist,target=dist \ |
| 430 | uv pip install dist/*.whl |
| 431 | |
| 432 | ADD ./tests/ ./tests/ |
| 433 | ADD ./examples/ ./examples/ |
| 434 | ADD ./benchmarks/ ./benchmarks/ |
| 435 | ADD ./vllm/collect_env.py . |
| 436 | ADD ./docker/ ./docker/ |
| 437 | ADD ./.buildkite/ ./.buildkite/ |
| 438 | # cmake/ is needed by tests/test_cmake_utils.py, which includes cmake/utils.cmake. |
| 439 | ADD ./cmake/ ./cmake/ |
| 440 | # tools/ carries repo-tooling code that a few tests exercise directly |
| 441 | # (e.g. tests/tools/test_check_test_tethering.py imports |
| 442 | # tools.pre_commit.check_test_tethering). |
| 443 | ADD ./tools/ ./tools/ |
| 444 | |
| 445 | # install development dependencies (for testing) |
| 446 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 447 | uv pip install -e tests/vllm_test_utils |
| 448 | |
| 449 | # enable fast downloads from hf (for testing) |
| 450 | ENV HF_XET_HIGH_PERFORMANCE 1 |
| 451 | |
| 452 | # increase timeout for hf downloads (for testing) |
| 453 | ENV HF_HUB_DOWNLOAD_TIMEOUT 60 |
| 454 | |
| 455 | ######################### RELEASE IMAGE ######################### |
| 456 | FROM base-arch AS vllm-openai |
| 457 | |
| 458 | WORKDIR /vllm-workspace |
| 459 | |
| 460 | RUN --mount=type=cache,target=/root/.cache/uv \ |
| 461 | --mount=type=cache,target=/root/.cache/ccache \ |
| 462 | --mount=type=bind,from=vllm-build,src=/vllm-workspace/dist,target=dist \ |
| 463 | uv pip install "$(realpath dist/*.whl)[audio,bench]" |
| 464 | |
| 465 | # Add labels to document build configuration |
| 466 | LABEL org.opencontainers.image.title="vLLM CPU" |
| 467 | LABEL org.opencontainers.image.description="vLLM inference engine for CPU platforms" |
| 468 | LABEL org.opencontainers.image.vendor="vLLM Project" |
| 469 | LABEL org.opencontainers.image.source="https://github.com/vllm-project/vllm" |
| 470 | |
| 471 | # Build configuration labels |
| 472 | ARG TARGETARCH |
| 473 | ARG VLLM_CPU_X86 |
| 474 | ARG VLLM_CPU_ARM_BF16 |
| 475 | ARG PYTHON_VERSION |
| 476 | |
| 477 | LABEL ai.vllm.build.target-arch="${TARGETARCH}" |
| 478 | LABEL ai.vllm.build.cpu-x86="${VLLM_CPU_X86:-false}" |
| 479 | LABEL ai.vllm.build.cpu-arm-bf16="${VLLM_CPU_ARM_BF16:-false}" |
| 480 | LABEL ai.vllm.build.python-version="${PYTHON_VERSION:-3.12}" |
| 481 | |
| 482 | # Copy the examples directory (including the chat/tool templates) so it is |
| 483 | # present in the released image, as the CUDA image ships it too. The vllm-test |
| 484 | # stage above adds examples/ for testing only, so without this the published |
| 485 | # vllm-openai-cpu image would not ship examples/*.jinja. |
| 486 | COPY examples examples |
| 487 | COPY tools/recipes tools/recipes |
| 488 | |
| 489 | ENTRYPOINT ["vllm", "serve"] |