Dockerfile 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. # syntax=docker/dockerfile:1.7
  2. # DeepSeek-V4-Flash DSpark — from-source build for DGX Spark (aarch64/sm_121a)
  3. # EXPERIMENTAL. Builds vLLM + FlashInfer + NCCL + b12x from the
  4. # local-inference-lab "eldritch" b12x fork at the newest DS4/DSpark branch, so we
  5. # are not limited to the pre-built aidendle94 image.
  6. #
  7. # Derived from docker-images/glm52-nf3-hybrid (same generic from-source harness:
  8. # torch/deps from the cu130 wheel index via a hash-locked requirements file,
  9. # FlashInfer/vLLM built from source wheels, b12x editable install). GLM-specific
  10. # overlay/patches are dropped; only the branch-pinned versions.env differs.
  11. #
  12. # All build inputs pinned in versions.env and locks/. We do NOT reuse the GLM
  13. # python-build/python-runtime locks (they pin torch 2.11 / flashinfer 0.6.12).
  14. # Regenerate them for THIS stack first:
  15. # bash gen-locks.sh # -> writes locks/python-build.txt & python-runtime.txt
  16. #
  17. # Build: cd docker-images/deepseek-v4-flash-dspark-src && bash build.sh
  18. ARG CUDA_BASE_IMAGE
  19. ARG CUDA_BASE_DIGEST
  20. FROM ${CUDA_BASE_IMAGE}@${CUDA_BASE_DIGEST} AS apt-base
  21. ARG UV_VERSION
  22. ARG PYTORCH_INDEX_URL
  23. ARG PYPI_INDEX_URL
  24. ARG TORCH_CUDA_ARCH_LIST=12.1a
  25. ENV DEBIAN_FRONTEND=noninteractive \
  26. PIP_BREAK_SYSTEM_PACKAGES=1 \
  27. UV_SYSTEM_PYTHON=1 UV_BREAK_SYSTEM_PACKAGES=1 UV_LINK_MODE=copy \
  28. TORCH_CUDA_ARCH_LIST=${TORCH_CUDA_ARCH_LIST} \
  29. TRITON_PTXAS_PATH=/usr/local/cuda/bin/ptxas
  30. COPY locks/apt-sources.list /tmp/apt-sources.list
  31. COPY locks/apt-packages.txt /tmp/apt-packages.txt
  32. COPY locks/python-bootstrap.txt /tmp/python-bootstrap.txt
  33. COPY locks/python-build.txt /tmp/python-build.txt
  34. RUN rm -f /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources \
  35. && cp /tmp/apt-sources.list /etc/apt/sources.list \
  36. && apt-get update \
  37. && grep -vE '^\s*(#|$)' /tmp/apt-packages.txt \
  38. | xargs apt-get install -y --no-install-recommends \
  39. && rm -rf /var/lib/apt/lists/* \
  40. && python3 -m pip install --no-cache-dir --require-hashes --no-deps \
  41. -r /tmp/python-bootstrap.txt --index-url ${PYPI_INDEX_URL}
  42. FROM apt-base AS torch-base
  43. RUN --mount=type=cache,id=uv-cache,target=/root/.cache/uv \
  44. uv pip install --require-hashes -r /tmp/python-build.txt \
  45. --index-url ${PYPI_INDEX_URL} --extra-index-url ${PYTORCH_INDEX_URL} \
  46. --index-strategy unsafe-best-match
  47. FROM torch-base AS base
  48. ARG NCCL_REPO NCCL_REF
  49. # NCCL_REF may be a tag, a branch, or a commit SHA (the DS4 fork pins a SHA), so
  50. # check out the ref rather than `git clone -b` (which only accepts branch/tag).
  51. RUN git clone ${NCCL_REPO} /opt/nccl \
  52. && cd /opt/nccl \
  53. && git checkout ${NCCL_REF} \
  54. && make -j $(nproc) src.build \
  55. NVCC_GENCODE="-gencode=arch=compute_121,code=sm_121" \
  56. && make install PREFIX=/usr/local && ldconfig
  57. FROM base AS flashinfer-builder
  58. ARG FLASHINFER_REPO FLASHINFER_REF
  59. ARG FLASHINFER_CUDA_ARCH_LIST=12.1a
  60. ARG SOURCE_DATE_EPOCH BUILD_JOBS
  61. ENV FLASHINFER_CUDA_ARCH_LIST=${FLASHINFER_CUDA_ARCH_LIST}
  62. RUN git clone --recursive ${FLASHINFER_REPO} /workspace/flashinfer \
  63. && cd /workspace/flashinfer \
  64. && git checkout ${FLASHINFER_REF} \
  65. && git submodule update --init --recursive
  66. WORKDIR /workspace/flashinfer
  67. RUN --mount=type=cache,id=uv-cache,target=/root/.cache/uv \
  68. --mount=type=cache,id=ccache,target=/root/.ccache \
  69. _j="${BUILD_JOBS:-$(nproc)}" \
  70. && export MAX_JOBS="${_j}" CMAKE_BUILD_PARALLEL_LEVEL="${_j}" \
  71. && sed -i '/^license-files/d' pyproject.toml \
  72. && sed -i 's|^license = .*|license = {text = "Apache-2.0"}|' pyproject.toml \
  73. && uv build --no-build-isolation --wheel . --out-dir=/wheels -v \
  74. && cd flashinfer-cubin \
  75. && sed -i '/^license-files/d' pyproject.toml \
  76. && sed -i 's|^license = .*|license = {text = "Apache-2.0"}|' pyproject.toml \
  77. && uv build --no-build-isolation --wheel . --out-dir=/wheels -v \
  78. && cd ../flashinfer-jit-cache \
  79. && sed -i '/^license-files/d' pyproject.toml \
  80. && sed -i 's|^license = .*|license = {text = "Apache-2.0"}|' pyproject.toml \
  81. && uv build --no-build-isolation --wheel . --out-dir=/wheels -v
  82. FROM base AS vllm-builder
  83. ARG VLLM_REPO VLLM_REF VLLM_COMMIT
  84. ARG SOURCE_DATE_EPOCH BUILD_JOBS
  85. # Force DGX Spark arch (sm_121a). The fork's CMake otherwise falls back to the
  86. # torch wheel's sm_120, but our FP4/`cvt.e2m1x2.f32` paths require sm_121a.
  87. ARG TORCH_CUDA_ARCH_LIST=12.1a
  88. ENV TORCH_CUDA_ARCH_LIST=${TORCH_CUDA_ARCH_LIST} CUTE_DSL_ARCH=sm_121a
  89. RUN git clone --recursive ${VLLM_REPO} /workspace/vllm \
  90. && cd /workspace/vllm \
  91. && git checkout ${VLLM_COMMIT} \
  92. && git submodule update --init --recursive
  93. COPY patches/ /patches/
  94. COPY apply-arch.py /apply-arch.py
  95. RUN cd /workspace/vllm \
  96. && for p in /patches/*.patch; do [ -f "$p" ] && patch -p1 --forward < "$p" || true; done \
  97. && python3 /apply-arch.py
  98. WORKDIR /workspace/vllm
  99. RUN --mount=type=cache,id=uv-cache,target=/root/.cache/uv \
  100. --mount=type=cache,id=ccache,target=/root/.ccache \
  101. echo "DIAG patch=$(command -v patch || echo MISSING)" \
  102. && echo "DIAG forced_arch_lines=$(grep -c _forced_arch CMakeLists.txt || echo 0)" \
  103. && echo "DIAG supported:" && grep -n 'CUDA_SUPPORTED_ARCHS \"7.5' CMakeLists.txt \
  104. && echo "DIAG TORCH_CUDA_ARCH_LIST=[${TORCH_CUDA_ARCH_LIST} ]" \
  105. && _j="${BUILD_JOBS:-$(nproc)}" \
  106. && export MAX_JOBS="${_j}" CMAKE_BUILD_PARALLEL_LEVEL="${_j}" \
  107. && python3 use_existing_torch.py \
  108. && sed -i '/^license-files/d' pyproject.toml \
  109. && sed -i 's|^license = .*|license = {text = "Apache-2.0"}|' pyproject.toml \
  110. && uv build --no-build-isolation --wheel . --out-dir=/wheels -v
  111. FROM base AS b12x-builder
  112. ARG B12X_REPO B12X_REF B12X_COMMIT
  113. ARG TORCH_CUDA_ARCH_LIST=12.1a
  114. ENV TORCH_CUDA_ARCH_LIST=${TORCH_CUDA_ARCH_LIST} CUTE_DSL_ARCH=sm_121a
  115. RUN git clone --recursive ${B12X_REPO} /opt/b12x \
  116. && cd /opt/b12x \
  117. && git checkout ${B12X_REF} \
  118. && pip install --no-cache-dir -e . --no-build-isolation \
  119. -C setup.args="--cuda-arch=${TORCH_CUDA_ARCH_LIST}"
  120. FROM base AS runner
  121. ARG TORCH_CUDA_ARCH_LIST=12.1a
  122. ARG PYTORCH_INDEX_URL PYPI_INDEX_URL
  123. ARG CUTLASS_DSL_VERSION
  124. COPY locks/python-runtime.txt /tmp/python-runtime.txt
  125. WORKDIR /workspace
  126. COPY checksums/tiktoken.sha256 /tmp/tiktoken.sha256
  127. RUN mkdir -p tiktoken_encodings \
  128. && wget -O tiktoken_encodings/o200k_base.tiktoken https://openaipublic.blob.core.windows.net/encodings/o200k_base.tiktoken \
  129. && wget -O tiktoken_encodings/cl100k_base.tiktoken https://openaipublic.blob.core.windows.net/encodings/cl100k_base.tiktoken \
  130. && cd tiktoken_encodings && sha256sum -c /tmp/tiktoken.sha256
  131. ENV TIKTOKEN_ENCODINGS_BASE=/workspace/tiktoken_encodings
  132. RUN apt-get update && apt-get install -y --no-install-recommends libboost-dev libaio-dev \
  133. && rm -rf /var/lib/apt/lists/*
  134. # Install all wheels
  135. RUN --mount=type=bind,from=flashinfer-builder,source=/wheels,target=/fi-wheels \
  136. --mount=type=bind,from=vllm-builder,source=/wheels,target=/vllm-wheels \
  137. --mount=type=cache,id=uv-cache,target=/root/.cache/uv \
  138. uv pip install --require-hashes -r /tmp/python-runtime.txt \
  139. --index-url ${PYPI_INDEX_URL} --extra-index-url ${PYTORCH_INDEX_URL} \
  140. --index-strategy unsafe-best-match \
  141. && pip install --no-cache-dir --no-deps /fi-wheels/*.whl /vllm-wheels/*.whl
  142. # b12x: symlink full source tree (must include integration/ attention/ etc.)
  143. COPY --from=b12x-builder /opt/b12x/ /opt/b12x/
  144. RUN rm -rf /usr/local/lib/python3.12/dist-packages/b12x* \
  145. && ln -sf /opt/b12x/b12x /usr/local/lib/python3.12/dist-packages/b12x \
  146. && pip install --no-cache-dir -e /opt/b12x --no-build-isolation --no-deps \
  147. -C setup.args="--cuda-arch=${TORCH_CUDA_ARCH_LIST}"
  148. RUN pip install --no-cache-dir \
  149. nvidia-cutlass-dsl==${CUTLASS_DSL_VERSION} \
  150. nvidia-cutlass-dsl-libs-cu13==${CUTLASS_DSL_VERSION}
  151. # NCCL symlink for torch
  152. RUN rm -f /usr/local/lib/python3.12/dist-packages/nvidia/nccl/lib/libnccl.so.2 \
  153. && ln -s /usr/local/lib/libnccl.so.2 \
  154. /usr/local/lib/python3.12/dist-packages/nvidia/nccl/lib/libnccl.so.2
  155. ENTRYPOINT []
  156. CMD ["bash"]