diff --git a/.github/workflows/release-docker-cu134-nightly.yml b/.github/workflows/release-docker-cu134-nightly.yml new file mode 100644 index 000000000..4310a7c34 --- /dev/null +++ b/.github/workflows/release-docker-cu134-nightly.yml @@ -0,0 +1,104 @@ +name: Release Docker Images Nightly (CUDA 13.4 Rubin) +# +# Builds and publishes nightly CUDA 13.4 / Rubin (sm_107) images from +# docker/Dockerfile.cu134, aarch64 only: +# - lmsysorg/sglang:nightly-cu134-{date}-{sha} +# - lmsysorg/sglang:nightly-cu134 +# + +on: + workflow_dispatch: + inputs: + image_repo: + description: "Docker Hub repo to push to. Use lmsysorg/sglang-staging for testing." + required: false + default: "lmsysorg/sglang" + docker_target: + description: "Dockerfile stage to build and publish." + required: false + default: "runtime" + build_only: + description: "Build and validate without logging in or pushing." + required: false + type: boolean + default: false + schedule: + # Offset from the other nightly docker builds; this one runs long. + - cron: "0 10 * * *" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-arm64: + if: github.repository == 'sgl-project/sglang' + runs-on: arm-docker-build-node + environment: ${{ (github.event_name == 'schedule' || !inputs.build_only) && 'prod' || null }} + # Cold builds recompile three CUDA wheels from source. + timeout-minutes: 360 + + steps: + - name: Delete huge unnecessary tools folder + run: rm -rf /opt/hostedtoolcache + + - name: Cleanup workspace (remove root-owned files from prior runs) + run: sudo rm -rf "$GITHUB_WORKSPACE"/* || true + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Compute image metadata + id: meta + run: | + set -euo pipefail + date_tag="$(date +%Y%m%d)" + commit_hash="$(git rev-parse --short=7 HEAD)" + image_repo="${{ inputs.image_repo || 'lmsysorg/sglang' }}" + echo "image_repo=${image_repo}" >> "$GITHUB_OUTPUT" + echo "tag=nightly-cu134-${date_tag}-${commit_hash}" >> "$GITHUB_OUTPUT" + echo "tag_rolling=nightly-cu134" >> "$GITHUB_OUTPUT" + + - name: Login to Docker Hub + if: github.event_name == 'schedule' || !inputs.build_only + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build image + run: | + set -euo pipefail + docker buildx build \ + --builder default \ + --progress=plain \ + --platform linux/arm64 \ + --target "${{ inputs.docker_target || 'runtime' }}" \ + --build-arg BRANCH_TYPE=local \ + --build-arg BUILD_TYPE=all \ + --build-arg BUILD_JOBS="$(nproc)" \ + -f docker/Dockerfile.cu134 \ + -t "${{ steps.meta.outputs.image_repo }}:${{ steps.meta.outputs.tag }}" \ + -t "${{ steps.meta.outputs.image_repo }}:${{ steps.meta.outputs.tag_rolling }}" \ + . + + - name: Push image + if: github.event_name == 'schedule' || !inputs.build_only + run: | + set -euo pipefail + push_with_retry() { + for i in 1 2 3 4 5; do + docker push "$1" && return 0 + echo "push failed (attempt $i), retrying in 30s" + sleep 30 + done + return 1 + } + push_with_retry "${{ steps.meta.outputs.image_repo }}:${{ steps.meta.outputs.tag }}" + push_with_retry "${{ steps.meta.outputs.image_repo }}:${{ steps.meta.outputs.tag_rolling }}" + + - name: Cleanup local images + if: always() + run: | + docker rmi -f "${{ steps.meta.outputs.image_repo }}:${{ steps.meta.outputs.tag }}" || true + docker rmi -f "${{ steps.meta.outputs.image_repo }}:${{ steps.meta.outputs.tag_rolling }}" || true diff --git a/docker/Dockerfile.cu134 b/docker/Dockerfile.cu134 new file mode 100644 index 000000000..ec2b02dbb --- /dev/null +++ b/docker/Dockerfile.cu134 @@ -0,0 +1,1167 @@ +ARG CUDA_VERSION=13.4.0 +ARG UBUNTU_BASE_IMAGE=ubuntu:24.04 +ARG CUDA_PKG_VERSION=13-4 +ARG CUDA_PREVIEW_REPO=https://packages.nvidia.com/noble +ARG CUDA_PREVIEW_SUITE=prerelease/cuda/13.4.0 + +ARG TORCH_NIGHTLY_INDEX=https://download.pytorch.org/whl/nightly/cu134 +ARG TORCH_NIGHTLY_VERSION=2.15.0.dev20260818+cu134 +ARG TORCHVISION_NIGHTLY_VERSION=0.30.0.dev20260819+cu134 +ARG TORCHAUDIO_NIGHTLY_VERSION=2.11.0.dev20260818+cu134 + +ARG MANYLINUX_IMAGE=pytorch/manylinuxaarch64-builder:cuda13.4 +ARG DEEPGEMM_REF=dev +ARG DEEPEP_SOURCE_REF=sgl-deepep +ARG DEEPEP_PACKAGING_REF=sgl-deepep-packaging +ARG SGL_DEEP_EP_VERSION=0.1.0 + +######################################################## +# CUDA base: Ubuntu + CUDA 13.4 developer preview toolkit +######################################################## +FROM ${UBUNTU_BASE_IMAGE} AS cuda_base + +ARG CUDA_PKG_VERSION +ARG CUDA_PREVIEW_REPO +ARG CUDA_PREVIEW_SUITE + +RUN export DEBIAN_FRONTEND=noninteractive \ + && apt-get update \ + && apt-get install -y --no-install-recommends ca-certificates wget gnupg \ + && wget -q -O /tmp/nvidia-preview-keyring.deb "${CUDA_PREVIEW_REPO}/nvidia-preview-keyring.deb" \ + && dpkg -i /tmp/nvidia-preview-keyring.deb \ + && rm -f /tmp/nvidia-preview-keyring.deb \ + && printf '%s\n' \ + 'X-Repolib-Name: NVIDIA Packages (frozen)' \ + 'Types: deb' \ + "URIs: ${CUDA_PREVIEW_REPO}" \ + "Suites: ${CUDA_PREVIEW_SUITE}" \ + 'Components: main' \ + 'Signed-By: /usr/share/keyrings/nvidia-packages-preview.gpg' \ + 'Enabled: yes' \ + > /etc/apt/sources.list.d/nvidia-packages-preview.sources \ + && apt-get update \ + && apt-get install -y --no-install-recommends "cuda-toolkit-${CUDA_PKG_VERSION}" \ + && cuda_dir="$(ls -d /usr/local/cuda-1* 2>/dev/null | head -1)" \ + && test -n "${cuda_dir}" \ + && ln -sfn "${cuda_dir}" /usr/local/cuda \ + && /usr/local/cuda/bin/nvcc --version \ + && rm -rf /var/lib/apt/lists/* + +# The 13.4 preview repo ships no NCCL, but later stages need libnccl2 / +# libnccl-dev: pynccl_allocator JIT-compiles with -lnccl under symmetric memory. +# The repo must be removed again in this same layer, not left behind an apt pin: +# the devtools repo that nsight-systems-cli adds later publishes byte-identical +# release metadata (o=NVIDIA, l=NVIDIA CUDA, c=) on this same host, so any pin +# that stops the CUDA repo's older cuda-* packages from shadowing the 13.4 +# toolkit also blocks nsight-systems-cli. Removal is safe: the later +# `apt-get install libnccl2 libnccl-dev` resolves from dpkg status. +RUN export DEBIAN_FRONTEND=noninteractive \ + && case "$(dpkg --print-architecture)" in \ + arm64) repo_arch=sbsa ;; \ + amd64) repo_arch=x86_64 ;; \ + *) echo "unsupported arch: $(dpkg --print-architecture)" >&2; exit 1 ;; \ + esac \ + && wget -q -O /tmp/cuda-keyring.deb \ + "https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/${repo_arch}/cuda-keyring_1.1-1_all.deb" \ + && dpkg -i /tmp/cuda-keyring.deb \ + && rm -f /tmp/cuda-keyring.deb \ + && apt-get update \ + && apt-get install -y --no-install-recommends libnccl2 libnccl-dev \ + && test -e "/usr/lib/$(uname -m)-linux-gnu/libnccl.so" \ + && rm -f /etc/apt/sources.list.d/cuda*.list /etc/apt/sources.list.d/cuda*.sources \ + && dpkg -r cuda-keyring \ + && rm -rf /var/lib/apt/lists/* + +ENV PATH=/usr/local/cuda/bin:${PATH} \ + LD_LIBRARY_PATH=/usr/local/cuda/lib64 \ + NVIDIA_VISIBLE_DEVICES=all \ + NVIDIA_DRIVER_CAPABILITIES=compute,utility + +# nvidia-cutlass-dsl 4.6.2 has no sm_107 in its Arch enum, so on Rubin every +# CuTe DSL kernel dies with `KeyError: 'sm_107a'` at JIT compile. sm_100f is the +# family target covering all sm_10x; sm_100a would be arch-specific. Both DSL +# singletons need setting -- CUTE_DSL_ARCH for CuTeDSL and +# CUTE_EXPERIMENTAL_DSL_ARCH for CuteExperimentalDSL (the default bf16 GEMM) -- +# since either alone leaves the other half failing. +# Drop both once a cutlass-dsl release knows sm_107 natively. +ENV CUTE_DSL_ARCH=sm_100f \ + CUTE_EXPERIMENTAL_DSL_ARCH=sm_100f + +######################################################## +# Base stage +######################################################## +FROM cuda_base AS base + +ARG TARGETARCH +ARG BUILD_TYPE=all +ARG BRANCH_TYPE=remote +ARG SGL_KERNEL_VERSION=0.4.6.post1 +ARG SGL_VERSION +ARG SGL_DEEP_GEMM_VERSION=0.1.5.post2 +ARG USE_LATEST_SGLANG=0 +ARG GDRCOPY_VERSION=2.5.1 +ARG NCCL_VERSION=2.30.7 +ARG PIP_DEFAULT_INDEX +ARG UBUNTU_MIRROR +ARG GITHUB_ARTIFACTORY=github.com +ARG INSTALL_FLASHINFER_JIT_CACHE=0 +ARG FLASHINFER_VERSION=0.6.17 +ARG MOONCAKE_VERSION=0.3.12.post1 +ARG MSCCLPP_VERSION=sglang-v0.9.1 + +ENV DEBIAN_FRONTEND=noninteractive \ + CUDA_HOME=/usr/local/cuda \ + GDRCOPY_HOME=/usr/src/gdrdrv-${GDRCOPY_VERSION}/ \ + FLASHINFER_VERSION=${FLASHINFER_VERSION} + +# Add GKE default lib and bin locations +ENV PATH="${PATH}:/usr/local/nvidia/bin" \ + LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/local/nvidia/lib:/usr/local/nvidia/lib64" + +# Replace Ubuntu sources if specified +RUN if [ -n "$UBUNTU_MIRROR" ]; then \ + sed -i "s|http://.*archive.ubuntu.com|$UBUNTU_MIRROR|g" /etc/apt/sources.list && \ + sed -i "s|http://.*security.ubuntu.com|$UBUNTU_MIRROR|g" /etc/apt/sources.list; \ +fi + +# Python setup (combined with apt update to reduce layers) +# Ubuntu 24.04 ships Python 3.12 in main, so we no longer need the deadsnakes +# PPA. Dropping it avoids transient Launchpad 504s in `add-apt-repository`. +RUN --mount=type=cache,target=/var/cache/apt,id=base-apt \ + apt update && apt install -y --no-install-recommends wget software-properties-common \ + && apt install -y --no-install-recommends python3.12-full python3.12-dev \ + && update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 2 \ + && update-alternatives --set python3 /usr/bin/python3.12 \ + # Fix for apt-add-repository + && cd /usr/lib/python3/dist-packages/ \ + && ln -s apt_pkg.cpython-312-*-linux-gnu.so apt_pkg.so + +# create virtual env for sglang to avoid conflict with system python packages +RUN python3 -m venv /opt/sglang +ENV PATH="/opt/sglang/bin:${PATH}" + +# Install system dependencies (organized by category for better caching) +RUN --mount=type=cache,target=/var/cache/apt,id=base-apt \ + apt-get update && apt-get install -y --no-install-recommends \ + # Core system utilities + ca-certificates \ + software-properties-common \ + netcat-openbsd \ + kmod \ + unzip \ + openssh-server \ + curl \ + wget \ + lsof \ + locales \ + # Build essentials (needed for framework stage) + build-essential \ + cmake \ + perl \ + patchelf \ + ccache \ + git-lfs \ + # MPI and NUMA + libopenmpi-dev \ + libnuma1 \ + libnuma-dev \ + numactl \ + # transformers multimodal VLM + ffmpeg \ + # InfiniBand/RDMA + libibverbs-dev \ + libibverbs1 \ + libibumad3 \ + librdmacm1 \ + libnl-3-200 \ + libnl-route-3-200 \ + libnl-route-3-dev \ + libnl-3-dev \ + ibverbs-providers \ + infiniband-diags \ + perftest \ + # Development libraries + libgoogle-glog-dev \ + libgtest-dev \ + libjsoncpp-dev \ + libunwind-dev \ + libboost-all-dev \ + libssl-dev \ + libgrpc-dev \ + libgrpc++-dev \ + libprotobuf-dev \ + protobuf-compiler \ + protobuf-compiler-grpc \ + pybind11-dev \ + libhiredis-dev \ + libcurl4-openssl-dev \ + libczmq4 \ + libczmq-dev \ + libfabric-dev \ + linux-libc-dev \ + # Package building tools + devscripts \ + debhelper \ + fakeroot \ + dkms \ + check \ + libsubunit0 \ + libsubunit-dev \ + && ln -sf /usr/bin/python3.12 /usr/bin/python \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +# Replace pip global cache if specified +RUN if [ -n "${PIP_DEFAULT_INDEX}" ]; then \ + python3 -m pip config set global.index-url ${PIP_DEFAULT_INDEX}; \ +fi + +# GDRCopy installation +RUN mkdir -p /tmp/gdrcopy && cd /tmp \ + && curl --retry 3 --retry-delay 2 -fsSL -o v${GDRCOPY_VERSION}.tar.gz \ + https://${GITHUB_ARTIFACTORY}/NVIDIA/gdrcopy/archive/refs/tags/v${GDRCOPY_VERSION}.tar.gz \ + && tar -xzf v${GDRCOPY_VERSION}.tar.gz && rm v${GDRCOPY_VERSION}.tar.gz \ + && cd gdrcopy-${GDRCOPY_VERSION}/packages \ + && CUDA=/usr/local/cuda ./build-deb-packages.sh \ + && dpkg -i gdrdrv-dkms_*.deb libgdrapi_*.deb gdrcopy-tests_*.deb gdrcopy_*.deb \ + && cd / && rm -rf /tmp/gdrcopy + +# Fix DeepEP IBGDA symlink +RUN ln -sf /usr/lib/$(uname -m)-linux-gnu/libmlx5.so.1 /usr/lib/$(uname -m)-linux-gnu/libmlx5.so + +# Set up locale +RUN locale-gen en_US.UTF-8 +ENV LANG=en_US.UTF-8 \ + LANGUAGE=en_US:en \ + LC_ALL=en_US.UTF-8 + +######################################################## +########## PARALLEL BUILDER STAGES #################### +######################################################## +# +# These stages run IN PARALLEL via BuildKit: +# +# base +# | +# +-- torch_deps ------> flashinfer_cache (needs flashinfer) +# | \-> hpc_ops_builder (cmake-only build) +# | +# +-- devtools_builder (independent) +# +-- gateway_builder (independent, only needs gateway source) +# | +# v +# framework (combines all artifacts) +# + +######################################################## +# PARALLEL STAGE 0: cu134 wheel builders +######################################################## +FROM ${MANYLINUX_IMAGE} AS cu134_wheel_base + +ARG TORCH_NIGHTLY_INDEX +ARG TORCH_NIGHTLY_VERSION +ARG PYTHON_TAG=cp312-cp312 +ARG GITHUB_ARTIFACTORY=github.com +ENV PYTHON_ROOT_PATH=/opt/python/${PYTHON_TAG} +ENV PATH=/opt/cmake/bin:${PYTHON_ROOT_PATH}/bin:${PATH} +ENV CUDA_HOME=/usr/local/cuda +ENV CPLUS_INCLUDE_PATH=/usr/local/cuda/include/cccl +ENV C_INCLUDE_PATH=/usr/local/cuda/include/cccl +ENV LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64:/usr/local/cuda/lib64 + +RUN set -eux; \ + arch="$(uname -m)"; \ + if [ "${arch}" = "aarch64" ]; then cuda_target=sbsa; else cuda_target="${arch}"; fi; \ + stub="/usr/local/cuda/targets/${cuda_target}-linux/lib/stubs/libcuda.so"; \ + test -f "${stub}"; \ + mkdir -p /usr/lib64 "/usr/lib/${arch}-linux-gnu"; \ + ln -sf "${stub}" /usr/lib64/libcuda.so; \ + ln -sf "${stub}" "/usr/lib/${arch}-linux-gnu/libcuda.so" + +RUN --mount=type=cache,id=cu134-wheels-pip,target=/root/.cache/pip \ + ${PYTHON_ROOT_PATH}/bin/pip install --upgrade pip \ + && ${PYTHON_ROOT_PATH}/bin/pip install "torch==${TORCH_NIGHTLY_VERSION}" \ + --index-url "${TORCH_NIGHTLY_INDEX}" \ + && ${PYTHON_ROOT_PATH}/bin/python -c "import torch; print('builder torch', torch.__version__)" + +######################################################## +# cu134 wheel: sglang-kernel +######################################################## +FROM cu134_wheel_base AS cu134_wheel_sglkernel + +ARG CMAKE_VERSION=3.31.1 +ARG CCACHE_VERSION=4.12.1 +ARG NVCC_THREADS=8 +ARG BUILD_JOBS=0 + +RUN yum install -y --nogpgcheck gcc gcc-c++ make wget tar numactl-devel libibverbs libzstd-devel \ + && yum --enablerepo=powertools install -y --nogpgcheck xxhash-devel \ + && ln -sfv /usr/lib64/libibverbs.so.1 /usr/lib64/libibverbs.so \ + && yum clean all && rm -rf /var/cache/yum + +RUN set -eux; \ + arch="$(uname -m)"; \ + tarball="cmake-${CMAKE_VERSION}-linux-${arch}.tar.gz"; \ + wget --progress=dot:giga "https://${GITHUB_ARTIFACTORY}/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${tarball}"; \ + tar -xzf "${tarball}"; \ + mv "cmake-${CMAKE_VERSION}-linux-${arch}" /opt/cmake; \ + rm -f "${tarball}"; \ + cmake --version + +RUN set -eux; \ + cd /tmp; \ + wget --progress=dot:giga "https://${GITHUB_ARTIFACTORY}/ccache/ccache/releases/download/v${CCACHE_VERSION}/ccache-${CCACHE_VERSION}.tar.xz"; \ + tar -xf "ccache-${CCACHE_VERSION}.tar.xz"; \ + cd "ccache-${CCACHE_VERSION}"; \ + mkdir build && cd build; \ + cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr -D ENABLE_TESTING=OFF \ + -D REDIS_STORAGE_BACKEND=OFF -D HTTP_STORAGE_BACKEND=OFF -D ENABLE_DOCUMENTATION=OFF ..; \ + make -j"$(nproc)"; make install; ccache --version; \ + rm -rf /tmp/ccache-${CCACHE_VERSION}* + +RUN --mount=type=cache,id=cu134-wheels-pip,target=/root/.cache/pip \ + ${PYTHON_ROOT_PATH}/bin/pip install ninja setuptools==75.0.0 wheel==0.41.0 numpy uv scikit-build-core + +WORKDIR /sgl-kernel +COPY python/sglang/kernels/aot /sgl-kernel/ + +RUN --mount=type=cache,id=cu134-sgl-kernel-ccache,target=/ccache \ + --mount=type=cache,id=cu134-wheels-pip,target=/root/.cache/pip \ + set -eux; \ + export CCACHE_DIR=/ccache CCACHE_BASEDIR=/sgl-kernel CCACHE_MAXSIZE=10G \ + CCACHE_COMPILERCHECK=content CCACHE_COMPRESS=true \ + CCACHE_SLOPPINESS=file_macro,time_macros,include_file_mtime,include_file_ctime \ + CMAKE_C_COMPILER_LAUNCHER=ccache CMAKE_CXX_COMPILER_LAUNCHER=ccache \ + CMAKE_CUDA_COMPILER_LAUNCHER=ccache; \ + if [ "${BUILD_JOBS}" -gt 0 ] 2>/dev/null; then \ + export CMAKE_BUILD_PARALLEL_LEVEL="${BUILD_JOBS}"; \ + else \ + export CMAKE_BUILD_PARALLEL_LEVEL="$(echo "$(( $(nproc) * 2 / 3 )) 64" | awk '{print ($1 < $2) ? $1 : $2}')"; \ + fi; \ + export CMAKE_ARGS="-DSGL_KERNEL_CXX_STANDARD=20 -DSGL_KERNEL_COMPILE_THREADS=${NVCC_THREADS} -DGITHUB_ARTIFACTORY=${GITHUB_ARTIFACTORY}"; \ + ${PYTHON_ROOT_PATH}/bin/python -m uv build --wheel -Cbuild-dir=build . --color=always --no-build-isolation; \ + PYTHON=${PYTHON_ROOT_PATH}/bin/python ./rename_wheels.sh; \ + mkdir -p /wheels && cp dist/*.whl /wheels/; \ + ls -la /wheels + +######################################################## +# cu134 wheel: sgl-deep-gemm +######################################################## +FROM cu134_wheel_base AS cu134_wheel_deepgemm + +ARG DEEPGEMM_REF +ARG SGL_DEEP_GEMM_VERSION=0.1.5.post2 +ARG TVM_FFI_VERSION=0.1.11 + +RUN yum install -y --nogpgcheck git wget tar gcc gcc-c++ make \ + && yum clean all && rm -rf /var/cache/yum + +RUN --mount=type=cache,id=cu134-wheels-pip,target=/root/.cache/pip \ + ${PYTHON_ROOT_PATH}/bin/pip install ninja setuptools wheel build numpy "apache-tvm-ffi==${TVM_FFI_VERSION}" + +RUN git clone --recursive --depth 1 --branch "${DEEPGEMM_REF}" \ + https://${GITHUB_ARTIFACTORY}/sgl-project/DeepGEMM.git /deepgemm + +COPY scripts/rename_sgl_deep_gemm_whl.sh /rename_sgl_deep_gemm_whl.sh + +RUN --mount=type=cache,id=cu134-wheels-pip,target=/root/.cache/pip \ + set -eux; \ + cd /deepgemm; \ + sed -i "s/'-std=c++17'/'-std=c++20'/g" \ + build_sgl_deep_gemm.sh setup.py sgl_deep_gemm/__init__.py; \ + printf '%s' "${SGL_DEEP_GEMM_VERSION}" > sgl_deep_gemm/VERSION; \ + bash build_sgl_deep_gemm.sh; \ + bash /rename_sgl_deep_gemm_whl.sh dist cu134 "$(uname -m)"; \ + mkdir -p /wheels && cp dist/*.whl /wheels/; \ + ls -la /wheels + +######################################################## +# cu134 wheel: sgl-deep-ep +######################################################## +FROM cu134_wheel_base AS cu134_wheel_deepep + +ARG DEEPEP_SOURCE_REF +ARG DEEPEP_PACKAGING_REF +ARG SGL_DEEP_EP_VERSION +ARG GDRCOPY_VERSION=2.5.1 +ARG MAX_JOBS=48 + +RUN yum install -y --nogpgcheck --enablerepo=powertools \ + cmake curl gcc gcc-c++ git infiniband-diags libfabric libfabric-devel \ + libibverbs libibverbs-devel libibverbs-utils librdmacm librdmacm-devel \ + make patchelf perftest pkgconfig rdma-core wget \ + && yum clean all && rm -rf /var/cache/yum + +RUN set -eux; \ + git clone --depth 1 --branch "v${GDRCOPY_VERSION}" \ + https://${GITHUB_ARTIFACTORY}/NVIDIA/gdrcopy.git /opt/gdrcopy; \ + make -C /opt/gdrcopy CUDA="${CUDA_HOME}" prefix=/usr/local lib_install; \ + printf '%s\n' /usr/local/lib > /etc/ld.so.conf.d/gdrcopy.conf; \ + ldconfig; \ + test -f /usr/local/include/gdrapi.h; \ + ldconfig -p | grep -q libgdrapi + +RUN --mount=type=cache,id=cu134-wheels-pip,target=/root/.cache/pip \ + ${PYTHON_ROOT_PATH}/bin/pip install "auditwheel>=6.0" build ninja packaging setuptools wheel + +RUN git clone --recursive --depth 1 --branch "${DEEPEP_SOURCE_REF}" \ + https://${GITHUB_ARTIFACTORY}/sgl-project/DeepEP.git /deepep-source \ + && git clone --depth 1 --branch "${DEEPEP_PACKAGING_REF}" \ + https://${GITHUB_ARTIFACTORY}/sgl-project/DeepEP.git /deepep-packaging + +RUN set -eux; \ + printf '%s' "${SGL_DEEP_EP_VERSION}" > /deepep-packaging/sgl_deep_ep/VERSION; \ + sed -i 's/"-std=c++17"/"-std=c++20"/g' /deepep-source/setup.py; \ + ${PYTHON_ROOT_PATH}/bin/python - <<'PY' +import pathlib +p = pathlib.Path("/deepep-packaging/sgl_deep_ep/build_sgl_deep_ep.sh") +s = p.read_text() +if "13.4|13.4.*" not in s: + old = ' *)\n echo "Unsupported CUDA version: ${CUDA_VERSION}; expected 12.9 or 13.0"' + new = (' 13.4|13.4.*)\n CUDA_MAJOR=13\n CUDA_TAG=cu134\n ;;\n' + ' *)\n echo "Unsupported CUDA version: ${CUDA_VERSION}; expected 12.9, 13.0 or 13.4"') + assert old in s, "DeepEP packaging CUDA case changed shape; update this patch" + p.write_text(s.replace(old, new)) + print("patched build_sgl_deep_ep.sh for CUDA 13.4") +PY + +RUN --mount=type=cache,id=cu134-wheels-pip,target=/root/.cache/pip \ + set -eux; \ + arch="$(uname -m)"; \ + raw_dir="$(mktemp -d)"; \ + MAX_JOBS="${MAX_JOBS}" bash /deepep-packaging/sgl_deep_ep/build_sgl_deep_ep.sh \ + /deepep-source /deepep-packaging/sgl_deep_ep "${raw_dir}" 13.4 "${arch}"; \ + mkdir -p /wheels; \ + auditwheel repair \ + --plat "manylinux_2_28_${arch}" \ + --wheel-dir /wheels \ + --exclude libcuda.so.1 \ + --exclude libcudart.so.12 \ + --exclude libcudart.so.13 \ + --exclude libc10.so \ + --exclude libc10_cuda.so \ + --exclude libtorch.so \ + --exclude libtorch_cpu.so \ + --exclude libtorch_cuda.so \ + --exclude libtorch_python.so \ + --exclude libnvshmem_host.so.1 \ + --exclude libnvshmem_host.so.2 \ + --exclude libnvshmem_host.so.3 \ + --exclude libnccl.so.2 \ + --exclude libgdrapi.so.2 \ + --exclude libnvToolsExt.so.1 \ + "${raw_dir}"/*.whl; \ + rm -rf "${raw_dir}"; \ + ls -la /wheels + +# Collect all three so torch_deps can COPY from a single stage. +FROM base AS cu134_wheels +COPY --from=cu134_wheel_sglkernel /wheels /wheels +COPY --from=cu134_wheel_deepgemm /wheels /wheels +COPY --from=cu134_wheel_deepep /wheels /wheels +RUN ls -la /wheels && test "$(ls /wheels/*.whl | wc -l)" -eq 3 + +######################################################## +# PARALLEL STAGE 1: Torch/Deps Builder (starts from base) +######################################################## +FROM base AS torch_deps + +ARG CUDA_VERSION +ARG BUILD_TYPE +ARG SGL_KERNEL_VERSION +ARG GITHUB_ARTIFACTORY +ARG NCCL_VERSION +ARG TORCH_NIGHTLY_INDEX +ARG TORCH_NIGHTLY_VERSION +ARG TORCHVISION_NIGHTLY_VERSION +ARG TORCHAUDIO_NIGHTLY_VERSION + +WORKDIR /sgl-workspace + +# Locally built cu134 wheels for sglang-kernel / sgl-deep-ep / sgl-deep-gemm. +COPY --from=cu134_wheels /wheels /tmp/cu134_wheels + +# Rust toolchain for setuptools-rust extensions (e.g. sglang-grpc). +# Requires >= 1.85 (edition 2024). Inherited by framework via FROM torch_deps. +ENV PATH="/root/.cargo/bin:${PATH}" +RUN curl --proto '=https' --tlsv1.2 --retry 3 --retry-delay 2 -sSf https://sh.rustup.rs \ + | sh -s -- -y --no-modify-path --profile minimal \ + && rustc --version && cargo --version + +# Install sgl-kernel (from pre-built wheel) +RUN --mount=type=cache,target=/root/.cache/pip \ + python3 -m pip install --upgrade pip setuptools wheel html5lib six \ + && case "$CUDA_VERSION" in \ + 12.6.3) CUINDEX=126 ;; \ + 12.9.2) CUINDEX=129 ;; \ + 13.0.3) CUINDEX=130 ;; \ + 13.4.0) CUINDEX=134 ;; \ + *) echo "Unsupported CUDA version: $CUDA_VERSION" && exit 1 ;; \ + esac \ + && if [ "$CUDA_VERSION" = "12.6.3" ]; then \ + python3 -m pip install https://${GITHUB_ARTIFACTORY}/sgl-project/whl/releases/download/v${SGL_KERNEL_VERSION}/sglang_kernel-${SGL_KERNEL_VERSION}+cu124-cp310-abi3-manylinux2014_$(uname -m).whl --force-reinstall --no-deps \ + ; \ + elif [ "$CUDA_VERSION" = "12.9.2" ]; then \ + python3 -m pip install https://${GITHUB_ARTIFACTORY}/sgl-project/whl/releases/download/v${SGL_KERNEL_VERSION}/sglang_kernel-${SGL_KERNEL_VERSION}+cu129-cp310-abi3-manylinux2014_$(uname -m).whl --force-reinstall --no-deps \ + ; \ + elif [ "$CUDA_VERSION" = "13.0.3" ]; then \ + # --no-deps prevents pip from pulling torch from default PyPI + python3 -m pip install sglang-kernel==${SGL_KERNEL_VERSION} --force-reinstall --no-deps \ + ; \ + elif [ "$CUDA_VERSION" = "13.4.0" ]; then \ + # Use locally built sgl-* wheels. + python3 -m pip install --force-reinstall --no-deps /tmp/cu134_wheels/*.whl \ + ; \ + else \ + echo "Unsupported CUDA version: $CUDA_VERSION" && exit 1 \ + ; \ + fi + +# Copy dep spec + Rust crate source + proto files. setuptools-rust compiles the +# Rust extension during the stub wheel build; the crate's build.rs references +# ../../proto for tonic_build. Split from the pip install so source changes to +# these paths invalidate the dep-install layer, but Python source changes don't. +COPY python/pyproject.toml /tmp/sglang_deps/python/pyproject.toml +COPY rust/sglang-grpc /tmp/sglang_deps/rust/sglang-grpc +COPY rust/sglang-mm /tmp/sglang_deps/rust/sglang-mm +COPY proto /tmp/sglang_deps/proto + +# Install sglang dependencies (torch, transformers, etc.). CUDA 12 DeepEP +# wheels live only on the SGLang index, so preinstall the local-version wheel; +# it satisfies the public-version pyproject pin during the full dependency solve. +# Generate constraints.txt to prevent reinstalling these deps in later stages. +RUN --mount=type=cache,target=/root/.cache/pip \ + --mount=type=cache,target=/root/.cargo/registry \ + case "$CUDA_VERSION" in \ + 12.6.3) CUINDEX=126 ;; \ + 12.9.2) CUINDEX=129 ;; \ + 13.0.3) CUINDEX=130 ;; \ + 13.4.0) CUINDEX=134 ;; \ + *) echo "Unsupported CUDA version: $CUDA_VERSION" && exit 1 ;; \ + esac \ + && cd /tmp/sglang_deps/python \ + && mkdir -p sglang \ + && touch sglang/__init__.py \ + && echo '__version__ = "0.0.0"' > sglang/version.py \ + && touch README.md \ + && touch LICENSE \ + && SGL_DEEP_EP_VERSION="$(sed -n 's/^[[:space:]]*"sgl-deep-ep==\([^"]*\)",/\1/p' pyproject.toml)" \ + && test -n "${SGL_DEEP_EP_VERSION}" \ + && if [ "${CUDA_VERSION%%.*}" = "12" ]; then \ + python3 -m pip install \ + "sgl-deep-ep==${SGL_DEEP_EP_VERSION}+cu129" \ + --index-url "https://docs.sglang.ai/whl/cu129/" \ + --no-deps; \ + fi \ + && if [ "${CUDA_VERSION%%.*}" = "12" ]; then \ + sed -i 's/cuda-python>=13\.0/cuda-python>=12,<13/' pyproject.toml && \ + sed -i 's/flashinfer_python\[cu13\]/flashinfer_python[cu12]/' pyproject.toml && \ + sed -i 's/nvidia-cutlass-dsl\[cu13\]/nvidia-cutlass-dsl/' pyproject.toml; \ + fi \ + && if [ "$CUDA_VERSION" = "13.4.0" ]; then \ + TORCH_INDEX="${TORCH_NIGHTLY_INDEX}"; \ + python3 -m pip install --index-url "${TORCH_NIGHTLY_INDEX}" \ + "torch==${TORCH_NIGHTLY_VERSION}" \ + "torchvision==${TORCHVISION_NIGHTLY_VERSION}" \ + "torchaudio==${TORCHAUDIO_NIGHTLY_VERSION}" && \ + sed -i "s|^ \"torch==.*| \"torch==${TORCH_NIGHTLY_VERSION}\",|" pyproject.toml && \ + sed -i "s|^ \"torchaudio==.*| \"torchaudio==${TORCHAUDIO_NIGHTLY_VERSION}\",|" pyproject.toml && \ + sed -i "s|^ \"torchvision\",\$| \"torchvision==${TORCHVISION_NIGHTLY_VERSION}\",|" pyproject.toml && \ + sed -i 's|"torchcodec==[0-9.]*|"torchcodec|' pyproject.toml && \ + # Locally built sgl-* wheels already installed above, drop here. \ + sed -i 's|^ "sglang-kernel==.*| "sglang-kernel",|' pyproject.toml && \ + sed -i 's|^ "sgl-deep-ep==.*| "sgl-deep-ep",|' pyproject.toml && \ + sed -i 's|^ "sgl-deep-gemm==.*| "sgl-deep-gemm",|' pyproject.toml; \ + else \ + TORCH_INDEX="https://download.pytorch.org/whl/cu${CUINDEX}"; \ + fi \ + && python3 -m pip install --extra-index-url "${TORCH_INDEX}" ".[${BUILD_TYPE}]" \ + && if [ "${CUDA_VERSION%%.*}" = "13" ]; then \ + python3 -m pip install --force-reinstall --no-deps \ + "nvidia-nccl-cu13==${NCCL_VERSION}"; \ + fi \ + && if [ "${CUDA_VERSION%%.*}" = "12" ]; then \ + pip list --format=freeze | awk -F'==' '/-cu13(==|$)/ {print $1}' \ + | xargs -r python3 -m pip uninstall -y && \ + python3 -m pip install --index-url https://download.pytorch.org/whl/cu${CUINDEX} \ + torch==2.13.0 torchvision==0.28.0 torchaudio==2.11.0 --force-reinstall; \ + python3 -m pip install https://github.com/sgl-project/whl/releases/download/v${SGL_DEEP_GEMM_VERSION}/sgl_deep_gemm-${SGL_DEEP_GEMM_VERSION}+cu129-py3-none-manylinux2014_$(uname -m).whl --force-reinstall; \ + fi \ + && cd /sgl-workspace \ + && rm -rf /tmp/sglang_deps \ + && pip freeze | grep -v "^sglang==" > /sgl-workspace/constraints.txt + +# distro resolves to the apt python3-distro under /usr/lib/python3, which the runtime +# stage does not COPY; force a pip copy into /usr/local so it survives the stage split. +RUN python3 -m pip install --ignore-installed --no-deps distro + +# constraints.txt pins the cu134 nightly torch, which does not exist on PyPI; +# later stages cannot satisfy it without the nightly index in scope. +RUN if [ "$CUDA_VERSION" = "13.4.0" ]; then \ + python3 -m pip config set global.extra-index-url "${TORCH_NIGHTLY_INDEX}"; \ + fi + +######################################################## +# PARALLEL STAGE 2: HPC-Ops Builder (needs torch_deps) +######################################################## +FROM torch_deps AS hpc_ops_builder + +# HPC-Ops (https://github.com/Tencent/hpc-ops, MIT): fused attention / MoE / +# RoPE kernels from the Tencent Hunyuan AI Infra team, consumed by the opt-in +# hpc_ops attention and MoE runner backends. +ARG HPC_OPS_COMMIT=ab1a402724635507037426068f6cddc3d30dc0a8 + +WORKDIR /build + +# The kernels target Hopper (sm90a) only, so skip non-x86_64 images. +# setup.py derives the version from `git rev-parse`, so keep the .git dir +# (a source zip archive would not build). +RUN --mount=type=cache,target=/root/.cache/pip \ + mkdir -p /wheels && \ + if [ "$(uname -m)" = "x86_64" ]; then \ + git clone https://github.com/Tencent/hpc-ops.git && \ + cd hpc-ops && \ + git checkout ${HPC_OPS_COMMIT} && \ + python3 setup.py bdist_wheel -d /wheels; \ + fi + +######################################################## +# PARALLEL STAGE 3: FlashInfer Cache (needs torch_deps) +######################################################## +FROM torch_deps AS flashinfer_cache + +ARG CUDA_VERSION +ARG INSTALL_FLASHINFER_JIT_CACHE +ARG FLASHINFER_VERSION + +# Stage jit-cache/cubin artifacts into /flashinfer_jit_output for clean COPY later +RUN --mount=type=cache,target=/root/.cache/pip \ + case "$CUDA_VERSION" in \ + 12.6.3) CUINDEX=126 ;; \ + 12.9.2) CUINDEX=129 ;; \ + 13.0.3) CUINDEX=130 ;; \ + 13.4.0) CUINDEX=134 ;; \ + *) echo "Unsupported CUDA version: $CUDA_VERSION" && exit 1 ;; \ + esac \ + && mkdir -p /flashinfer_jit_output \ + # flashinfer-cubin is CUDA-version-agnostic, unlike jit-cache, so its index-url has no cu${CUINDEX} suffix + && python3 -m pip install flashinfer-cubin==${FLASHINFER_VERSION} --index-url https://flashinfer.ai/whl \ + && cp -r /opt/sglang/lib/python3.12/site-packages/flashinfer_cubin /flashinfer_jit_output/ \ + && cp -r /opt/sglang/lib/python3.12/site-packages/flashinfer_cubin-*.dist-info /flashinfer_jit_output/ \ + && if [ "$INSTALL_FLASHINFER_JIT_CACHE" = "1" ]; then \ + python3 -m pip install flashinfer-jit-cache==${FLASHINFER_VERSION} --index-url https://flashinfer.ai/whl/cu${CUINDEX} \ + && cp -r /opt/sglang/lib/python3.12/site-packages/flashinfer_jit_cache /flashinfer_jit_output/ \ + && cp -r /opt/sglang/lib/python3.12/site-packages/flashinfer_jit_cache-*.dist-info /flashinfer_jit_output/ ; \ + fi + +######################################################## +# PARALLEL STAGE 4: Dev Tools Builder (starts from base) +######################################################## +FROM base AS devtools_builder + +ARG GITHUB_ARTIFACTORY + +WORKDIR /tools + +# Minimal apt deps needed for oh-my-zsh install in this stage +# Full dev apt packages (gdb, vim, tmux, nsight, etc.) are installed in the framework stage +RUN --mount=type=cache,target=/var/cache/apt,id=devtools-apt \ + apt-get update && apt-get install -y --no-install-recommends zsh git \ + && rm -rf /var/lib/apt/lists/* + +# Download CLI tools (each in its own layer for parallel downloads) +RUN curl --retry 3 --retry-delay 2 -LSso /tools/diff-so-fancy \ + https://${GITHUB_ARTIFACTORY}/so-fancy/diff-so-fancy/releases/download/v1.4.4/diff-so-fancy \ + && chmod +x /tools/diff-so-fancy + +RUN curl --retry 3 --retry-delay 2 -LSso /tools/clang-format \ + https://${GITHUB_ARTIFACTORY}/muttleyxd/clang-tools-static-binaries/releases/download/master-32d3ac78/clang-format-16_linux-amd64 \ + && chmod +x /tools/clang-format + +RUN curl --retry 3 --retry-delay 2 -fsSL -o /tmp/clangd.zip \ + https://${GITHUB_ARTIFACTORY}/clangd/clangd/releases/download/18.1.3/clangd-linux-18.1.3.zip \ + && unzip -q /tmp/clangd.zip -d /tmp \ + && cp /tmp/clangd_18.1.3/bin/* /tools/ \ + && mkdir -p /tools/lib && cp -r /tmp/clangd_18.1.3/lib/* /tools/lib/ \ + && rm -rf /tmp/clangd.zip /tmp/clangd_18.1.3 + +RUN CMAKE_VERSION=3.31.1 \ + && ARCH=$(uname -m) \ + && CMAKE_INSTALLER="cmake-${CMAKE_VERSION}-linux-${ARCH}" \ + && curl --retry 3 --retry-delay 2 -fsSL -o "/tmp/${CMAKE_INSTALLER}.tar.gz" \ + "https://${GITHUB_ARTIFACTORY}/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${CMAKE_INSTALLER}.tar.gz" \ + && tar -xzf "/tmp/${CMAKE_INSTALLER}.tar.gz" -C /tmp \ + && cp -r "/tmp/${CMAKE_INSTALLER}/bin/"* /tools/ \ + && mkdir -p /tools/share && cp -r "/tmp/${CMAKE_INSTALLER}/share/"* /tools/share/ \ + && rm -rf "/tmp/${CMAKE_INSTALLER}" "/tmp/${CMAKE_INSTALLER}.tar.gz" + +RUN curl --proto '=https' --tlsv1.2 --retry 3 --retry-delay 2 -sSf https://just.systems/install.sh | \ + sed "s|https://github.com|https://${GITHUB_ARTIFACTORY}|g" | \ + bash -s -- --tag 1.42.4 --to /tools + +# Install oh-my-zsh and plugins +RUN sh -c "$(curl --retry 3 --retry-delay 2 -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended \ + && git clone --depth 1 https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-/root/.oh-my-zsh/custom}/plugins/zsh-autosuggestions \ + && git clone --depth 1 https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-/root/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting + +######################################################## +# PARALLEL STAGE 5: Gateway Builder (starts from base) +######################################################## +# Builds sgl-model-gateway in isolation so Python-only changes +# don't trigger a full Rust recompilation. +FROM base AS gateway_builder + +ARG GITHUB_ARTIFACTORY +ARG BRANCH_TYPE +ARG SGL_VERSION +ARG USE_LATEST_SGLANG + +WORKDIR /build + +# Copy ONLY the gateway source (not the full repo) +COPY sgl-model-gateway /build/sgl-model-gateway + +# Install Rust, build gateway binary and Python bindings, then clean up Rust toolchain +RUN --mount=type=cache,target=/root/.cache/pip \ + curl --proto '=https' --tlsv1.2 --retry 3 --retry-delay 2 -sSf https://sh.rustup.rs | sh -s -- -y \ + && export PATH="/root/.cargo/bin:${PATH}" \ + && python3 -m pip install maturin \ + && cd /build/sgl-model-gateway/bindings/python \ + && ulimit -n 65536 && maturin build --release --features vendored-openssl --out /build/gateway_wheels \ + && cd /build/sgl-model-gateway \ + && cargo build --release --bin sgl-model-gateway --features vendored-openssl \ + && cp target/release/sgl-model-gateway /build/sgl-model-gateway-bin \ + && rm -rf /root/.cargo /root/.rustup /build/sgl-model-gateway/target /build/sgl-model-gateway/bindings/python/target + +######################################################## +########## Final Framework Image ###################### +######################################################## +# +# Combines all artifacts from parallel builder stages +# +FROM torch_deps AS framework + +ARG BRANCH_TYPE +ARG BUILD_TYPE +ARG CUDA_VERSION +ARG SGL_VERSION +ARG USE_LATEST_SGLANG +ARG GITHUB_ARTIFACTORY +ARG MOONCAKE_VERSION +ARG MSCCLPP_VERSION +ARG TORCH_NIGHTLY_VERSION + +WORKDIR /sgl-workspace + +# ============================================================================= +# Copy artifacts from parallel builders +# ============================================================================= + +# Copy HPC-Ops wheel and install (empty on non-x86_64; kernels are sm90a-only) +COPY --from=hpc_ops_builder /wheels /tmp/wheels/hpc-ops +RUN --mount=type=cache,target=/root/.cache/pip \ + if ls /tmp/wheels/hpc-ops/*.whl >/dev/null 2>&1; then \ + pip install --no-deps /tmp/wheels/hpc-ops/*.whl; \ + fi && rm -rf /tmp/wheels/hpc-ops + +# Copy flashinfer cubin (always) and jit-cache (if installed) packages +COPY --from=flashinfer_cache /flashinfer_jit_output/ /opt/sglang/lib/python3.12/site-packages/ + +# Copy dev tools +COPY --from=devtools_builder /tools/diff-so-fancy /usr/local/bin/ +COPY --from=devtools_builder /tools/clang-format /usr/local/bin/ +COPY --from=devtools_builder /tools/clangd /usr/local/bin/ +COPY --from=devtools_builder /tools/lib /usr/local/lib/ +COPY --from=devtools_builder /tools/cmake /usr/local/bin/ +COPY --from=devtools_builder /tools/ctest /usr/local/bin/ +COPY --from=devtools_builder /tools/cpack /usr/local/bin/ +COPY --from=devtools_builder /tools/share/cmake-3.31 /usr/local/share/cmake-3.31 +COPY --from=devtools_builder /tools/just /usr/local/bin/ +COPY --from=devtools_builder /root/.oh-my-zsh /root/.oh-my-zsh + +# Install dev apt packages (need to re-run since we're in a different stage) +RUN --mount=type=cache,target=/var/cache/apt,id=framework-apt \ + apt-get update && apt-get install -y --no-install-recommends \ + gdb \ + ninja-build \ + vim \ + tmux \ + htop \ + zsh \ + tree \ + silversearcher-ag \ + cloc \ + pkg-config \ + bear \ + less \ + rdma-core \ + openssh-server \ + gnuplot \ + infiniband-diags \ + perftest \ + ibverbs-providers \ + libibumad3 \ + libibverbs1 \ + libnl-3-200 \ + libnl-route-3-200 \ + librdmacm1 \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +# Install NVIDIA development tools +RUN --mount=type=cache,target=/var/cache/apt,id=framework-apt \ + apt update -y \ + && apt install -y --no-install-recommends gnupg \ + && echo "deb http://developer.download.nvidia.com/devtools/repos/ubuntu2004/$(if [ "$(uname -m)" = "aarch64" ]; then echo "arm64"; else echo "amd64"; fi) /" | tee /etc/apt/sources.list.d/nvidia-devtools.list \ + && apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/$(if [ "$(uname -m)" = "aarch64" ]; then echo "arm64"; else echo "x86_64"; fi)/7fa2af80.pub \ + && apt update -y \ + && apt install -y --no-install-recommends nsight-systems-cli \ + && rm -rf /var/lib/apt/lists/* + +# ============================================================================= +# Python packages and tools (before source copy for better caching) +# ============================================================================= + +# Install Mooncake +RUN --mount=type=cache,target=/root/.cache/pip \ + CUDA_MAJOR="${CUDA_VERSION%%.*}" && \ + if [ "$CUDA_MAJOR" -ge 13 ]; then \ + python3 -m pip install mooncake-transfer-engine-cuda13==${MOONCAKE_VERSION}; \ + else \ + python3 -m pip install mooncake-transfer-engine==${MOONCAKE_VERSION}; \ + fi + +# Install MSCCL++ Python dependencies and package (builds extension via CMake through pip) +RUN --mount=type=cache,target=/root/.cache/pip \ + git clone --depth=1 --branch ${MSCCLPP_VERSION} https://${GITHUB_ARTIFACTORY}/microsoft/mscclpp.git /tmp/mscclpp \ + && case "${CUDA_VERSION}" in \ + 12.*) \ + CMAKE_ARGS="-DMSCCLPP_BYPASS_GPU_CHECK=ON -DMSCCLPP_USE_CUDA=ON -DMSCCLPP_GPU_ARCHS=80,90,100,100a,103,103a" \ + python3 -m pip install "/tmp/mscclpp[cuda12]"; \ + ;; \ + 13.*) \ + CMAKE_ARGS="-DMSCCLPP_BYPASS_GPU_CHECK=ON -DMSCCLPP_USE_CUDA=ON -DMSCCLPP_GPU_ARCHS=80,90,100,100a,103,103a" \ + python3 -m pip install "/tmp/mscclpp[cuda13]"; \ + ;; \ + *) \ + echo "Unsupported CUDA version for MSCCL++: ${CUDA_VERSION}" && exit 1; \ + ;; \ + esac \ + && rm -rf /tmp/mscclpp + +# Install essential Python packages (use constraints to prevent conflicts) +# +# pip only considers pre-release candidates when the requirement itself names +# one, so the constraints-pinned cu134 nightly must be restated here; otherwise +# runai-model-streamer's "torch<3.0.0,>=2.0.0" backtracks the whole resolve. +RUN --mount=type=cache,target=/root/.cache/pip \ + if [ "$CUDA_VERSION" = "13.4.0" ]; then TORCH_SPEC="torch==${TORCH_NIGHTLY_VERSION}"; else TORCH_SPEC=""; fi \ + && python3 -m pip install -c /sgl-workspace/constraints.txt \ + ${TORCH_SPEC} \ + datamodel_code_generator \ + pre-commit \ + pytest \ + black \ + isort \ + icdiff \ + uv \ + wheel \ + scikit-build-core \ + py-spy \ + cubloaty \ + google-cloud-storage \ + pandas \ + matplotlib \ + tabulate \ + termplotlib \ + "runai-model-streamer[s3,gcs,azure]>=0.15.7" + +# Per-CUDA-major package installs. The `nixl` stub package is needed (it owns +# the `nixl` import path) but unconditionally requires nixl-cu12, so we install +# it with --no-deps and pair it with the matching nixl-cu12 / nixl-cu13 binary +# to avoid shipping wrong-CUDA libs on cu13 images. +RUN --mount=type=cache,target=/root/.cache/pip if [ "${CUDA_VERSION%%.*}" = "12" ]; then \ + python3 -m pip install nixl nixl-cu12 --no-deps ; \ + python3 -m pip install "cuda-python>=12,<13" ; \ +elif [ "${CUDA_VERSION%%.*}" = "13" ]; then \ + python3 -m pip install nixl nixl-cu13 --no-deps ; \ + python3 -m pip install "cuda-python>=13,<14" ; \ +fi + +# Add yank script +COPY --chown=root:root --chmod=755 docker/configs/yank /usr/local/bin/yank + +# These configs are optional; users can override them by mounting their own files +COPY docker/configs/opt/.vimrc /opt/sglang/.vimrc +COPY docker/configs/opt/.tmux.conf /opt/sglang/.tmux.conf +COPY docker/configs/opt/.gitconfig /opt/sglang/.gitconfig + +# Configure development environment +COPY docker/configs/.zshrc /root/.zshrc + +# Fix Trivy-reported CVEs +# pip: urllib3 (CVE-2025-43859), pillow (CVE-2026-25990) +# binutils family: CVE-2025-{1147,1148,3198,5244,5245,7545,7546,8225,11082,11083,11412,11413,11414,11494,11839,11840} +# libgnutls30t64: CVE-2025-{9820,14831} +# libpam: CVE-2024-10963 +# libsqlite3-0: CVE-2025-{6965,7709} +# libtasn1-6: CVE-2025-13151 +# dpkg: CVE-2025-6297 +RUN python3 -m pip install --upgrade "urllib3>=2.6.3" "pillow>=12.1.1" +RUN --mount=type=cache,target=/var/cache/apt,id=framework-apt \ + apt-get update && apt-get install -y --only-upgrade \ + binutils binutils-common binutils-x86-64-linux-gnu libbinutils \ + libctf0 libctf-nobfd0 libgprofng0 libsframe1 \ + libgnutls30t64 \ + libpam-modules libpam-modules-bin libpam-runtime libpam0g \ + libsqlite3-0 libtasn1-6 \ + dpkg dpkg-dev libdpkg-perl \ + && rm -rf /var/lib/apt/lists/* + +# ============================================================================= +# Copy sglang source and do editable install (LAST for better caching) +# ============================================================================= + +# Copy local source if building from local +FROM scratch AS local_src +COPY . /src + +FROM framework AS framework_final + +ARG BRANCH_TYPE +ARG BUILD_TYPE +ARG CUDA_VERSION +ARG SGL_VERSION +ARG USE_LATEST_SGLANG + +WORKDIR /sgl-workspace + +COPY --from=local_src /src /tmp/local_src +RUN if [ "$BRANCH_TYPE" = "local" ]; then \ + cp -r /tmp/local_src /sgl-workspace/sglang; \ + elif [ "$USE_LATEST_SGLANG" = "1" ]; then \ + git clone --depth=1 https://github.com/sgl-project/sglang.git /sgl-workspace/sglang; \ + elif [ -z "$SGL_VERSION" ]; then \ + echo "ERROR: SGL_VERSION must be set when USE_LATEST_SGLANG=0 and BRANCH_TYPE!=local" && exit 1; \ + else \ + git clone --depth=1 --branch v${SGL_VERSION} https://github.com/sgl-project/sglang.git /sgl-workspace/sglang; \ + fi \ + && rm -rf /tmp/local_src + +# Editable install (fast - dependencies already installed via constraints) +# Clean up __pycache__/tests/pyc in same RUN to avoid writing ~28k files to layer +RUN --mount=type=cache,target=/root/.cache/pip \ + cd /sgl-workspace/sglang \ + && if [ "${CUDA_VERSION%%.*}" = "12" ]; then \ + sed -i 's/cuda-python>=13\.0/cuda-python>=12,<13/' python/pyproject.toml && \ + sed -i 's/flashinfer_python\[cu13\]/flashinfer_python[cu12]/' python/pyproject.toml && \ + sed -i 's/nvidia-cutlass-dsl\[cu13\]/nvidia-cutlass-dsl/' python/pyproject.toml; \ + fi \ + && python3 -m pip install --no-deps -e "python[${BUILD_TYPE}]" \ + && kernels lock python \ + && ( success=0; \ + # aarch64: kernels-community/sgl-flash-attn3 ships no arm variants; JIT-compile at runtime. + # Remove this branch once arm cubins are published upstream. + if [ "$(uname -m)" = "aarch64" ]; then \ + echo "Skipping kernels-community/sgl-flash-attn3 cubin download on aarch64 (no variants published upstream); kernels will be JIT-compiled at runtime"; \ + success=1; \ + else \ + for i in 1 2 3; do \ + echo "Attempt $i/3: downloading sgl-kernel cubins..." && \ + kernels download python && \ + success=1 && break; \ + echo "sgl-kernel cubin download failed, retrying in 30s..." && sleep 30; \ + done; \ + # x86: if no prebuilt sgl-flash-attn3 variant matches this torch+CUDA \ + # combo (e.g. cu129 publishes no torch>=2.10 cubin), fall back to \ + # runtime JIT instead of failing the build, mirroring the aarch64 branch. \ + if [ "$success" != "1" ]; then \ + echo "WARNING: no matching sgl-flash-attn3 cubin variant for this torch+CUDA; kernels will be JIT-compiled at runtime"; \ + success=1; \ + fi; \ + fi; \ + [ "$success" = "1" ] ) \ + && mkdir -p /root/.cache/huggingface /root/.cache/sglang \ + && ( if [ -f python/kernels.lock ]; then mv python/kernels.lock /root/.cache/sglang/; fi ) \ + && ( find /opt/sglang/lib/python3.12/site-packages -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true ) + + +# Install pre-built gateway artifacts from parallel builder +COPY --from=gateway_builder /build/sgl-model-gateway-bin /opt/sglang/bin/sgl-model-gateway +COPY --from=gateway_builder /build/gateway_wheels /tmp/gateway_wheels +RUN --mount=type=cache,target=/root/.cache/pip \ + python3 -m pip install --force-reinstall /tmp/gateway_wheels/*.whl \ + && rm -rf /tmp/gateway_wheels + +# Set workspace directory +WORKDIR /sgl-workspace/sglang + +# Keep build provenance at the end so metadata changes do not invalidate build layers. +ARG SGLANG_BUILD_COMMIT=unknown +ARG SGLANG_BUILD_URL= +ARG SGLANG_IMAGE_TAG=local/sglang:dev +ENV SGLANG_BUILD_COMMIT=${SGLANG_BUILD_COMMIT:-unknown} \ + SGLANG_BUILD_URL=${SGLANG_BUILD_URL:-} \ + SGLANG_IMAGE_TAG=${SGLANG_IMAGE_TAG:-local/sglang:dev} +LABEL org.opencontainers.image.source="https://github.com/sgl-project/sglang" \ + org.opencontainers.image.revision="${SGLANG_BUILD_COMMIT}" \ + org.opencontainers.image.version="${SGLANG_IMAGE_TAG}" \ + org.opencontainers.image.url="${SGLANG_BUILD_URL}" \ + ai.sglang.build.commit="${SGLANG_BUILD_COMMIT}" \ + ai.sglang.build.url="${SGLANG_BUILD_URL}" \ + ai.sglang.image.tag="${SGLANG_IMAGE_TAG}" + +######################################################## +########## Runtime Image ############################## +######################################################## +# +# PURPOSE: Production runtime environment with JIT support +# +# This stage creates a production-ready image containing: +# - Pre-installed SGLang and CUDA dependencies +# - Full CUDA toolchain for JIT compilation (DeepGEMM, Triton, FlashInfer) +# - Optimized for inference workloads and deployment +# - Smaller than framework (no dev tools like vim, tmux, nsight, etc.) +# +# Use this stage when you need: +# - Production deployment of SGLang +# - JIT compilation support for FP8/microscaling kernels +# - Ready-to-run inference server environment +# +# Note: Uses devel base for complete NVCC toolchain required by DeepGEMM JIT +FROM cuda_base AS runtime + +ARG CUDA_VERSION +ARG TARGETARCH +ARG GDRCOPY_VERSION=2.5.1 + +ENV DEBIAN_FRONTEND=noninteractive \ + CUDA_HOME=/usr/local/cuda \ + GDRCOPY_HOME=/usr/src/gdrdrv-${GDRCOPY_VERSION}/ + +# Add GKE default lib and bin locations + CUDA compiler paths for FlashInfer JIT +ENV PATH="${PATH}:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/cuda/nvvm/bin" \ + LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/local/nvidia/lib:/usr/local/nvidia/lib64" + +# Install runtime dependencies (devel base provides gcc/g++/build tools) +# Python 3.12 ships in Ubuntu 24.04 main, so no deadsnakes PPA needed. +RUN --mount=type=cache,target=/var/cache/apt,id=runtime-apt \ + apt-get update && apt-get install -y --no-install-recommends --allow-change-held-packages \ + # Python runtime + python3.12-full \ + python3.12-dev \ + wget \ + # Core system utilities + ca-certificates \ + netcat-openbsd \ + curl \ + git \ + # Runtime libraries + libopenmpi3 \ + libnuma1 \ + libibverbs1 \ + libibumad3 \ + librdmacm1 \ + libnl-3-200 \ + libnl-route-3-200 \ + ibverbs-providers \ + libgoogle-glog0v6t64 \ + libunwind8 \ + libboost-system1.83.0 \ + libboost-thread1.83.0 \ + libboost-filesystem1.83.0 \ + libgrpc++1.51t64 \ + libprotobuf32t64 \ + libhiredis1.1.0 \ + libcurl4 \ + libczmq4 \ + libfabric1 \ + libssl-dev \ + # RDMA runtime + rdma-core \ + infiniband-diags \ + perftest \ + # Build tools for JIT compilation + ninja-build \ + # NCCL packages needed for pynccl_allocator JIT compilation (-lnccl) + libnccl2 \ + libnccl-dev \ + # GPG key verification + gnupg2 \ + linux-libc-dev \ + && update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 2 \ + && update-alternatives --set python3 /usr/bin/python3.12 \ + && ln -sf /usr/bin/python3.12 /usr/bin/python \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +# create virtual env for sglang to avoid conflict with system python packages +RUN python3 -m venv /opt/sglang +ENV PATH="/opt/sglang/bin:${PATH}" + +# Set up locale +RUN apt-get update && apt-get install -y --no-install-recommends locales \ + && locale-gen en_US.UTF-8 \ + && rm -rf /var/lib/apt/lists/* + +ENV LANG=en_US.UTF-8 \ + LANGUAGE=en_US:en \ + LC_ALL=en_US.UTF-8 + +# Fix Trivy-reported CVEs (see framework stage for full CVE list) +RUN --mount=type=cache,target=/var/cache/apt,id=runtime-apt \ + apt-get update && apt-get install -y --only-upgrade \ + binutils binutils-common binutils-x86-64-linux-gnu libbinutils \ + libctf0 libctf-nobfd0 libgprofng0 libsframe1 \ + libgnutls30t64 \ + libpam-modules libpam-modules-bin libpam-runtime libpam0g \ + libsqlite3-0 libtasn1-6 \ + dpkg dpkg-dev libdpkg-perl \ + && rm -rf /var/lib/apt/lists/* + +# Copy Python site-packages from framework (already cleaned of __pycache__/tests/pyc files) +COPY --from=framework_final /opt/sglang/lib/python3.12/site-packages /opt/sglang/lib/python3.12/site-packages + +# Copy SGLang workspace +COPY --from=framework_final /sgl-workspace /sgl-workspace + +# Copy sgl-model-gateway binary +COPY --from=framework_final /opt/sglang/bin/sgl-model-gateway /opt/sglang/bin/sgl-model-gateway + +# Copy sglang binary +COPY --from=framework_final /opt/sglang/bin/sglang /opt/sglang/bin/sglang + +# Copy py-spy binary +COPY --from=framework_final /opt/sglang/bin/py-spy /opt/sglang/bin/py-spy + +# Copy cache for kernels from kernels community +COPY --from=framework_final /root/.cache/huggingface /root/.cache/huggingface +COPY --from=framework_final /root/.cache/sglang /root/.cache/sglang + +# Copy GDRCopy runtime libraries (but not the build artifacts) +COPY --from=framework_final /usr/lib/libgdrapi.so* /usr/lib/ +COPY --from=framework_final /usr/bin/gdrcopy_* /usr/bin/ +COPY --from=framework_final /usr/src/gdrdrv-2.5.1 /usr/src/gdrdrv-2.5.1 + +# Fix DeepEP IBGDA symlink in runtime +RUN ln -sf /usr/lib/$(uname -m)-linux-gnu/libmlx5.so.1 /usr/lib/$(uname -m)-linux-gnu/libmlx5.so + +WORKDIR /sgl-workspace/sglang + +# Keep build provenance at the end so metadata changes do not invalidate build layers. +ARG SGLANG_BUILD_COMMIT=unknown +ARG SGLANG_BUILD_URL= +ARG SGLANG_IMAGE_TAG=local/sglang:dev +ENV SGLANG_BUILD_COMMIT=${SGLANG_BUILD_COMMIT:-unknown} \ + SGLANG_BUILD_URL=${SGLANG_BUILD_URL:-} \ + SGLANG_IMAGE_TAG=${SGLANG_IMAGE_TAG:-local/sglang:dev} +LABEL org.opencontainers.image.source="https://github.com/sgl-project/sglang" \ + org.opencontainers.image.revision="${SGLANG_BUILD_COMMIT}" \ + org.opencontainers.image.version="${SGLANG_IMAGE_TAG}" \ + org.opencontainers.image.url="${SGLANG_BUILD_URL}" \ + ai.sglang.build.commit="${SGLANG_BUILD_COMMIT}" \ + ai.sglang.build.url="${SGLANG_BUILD_URL}" \ + ai.sglang.image.tag="${SGLANG_IMAGE_TAG}" + +# Default command +CMD ["/bin/bash"] diff --git a/python/sglang/kernels/aot/CMakeLists.txt b/python/sglang/kernels/aot/CMakeLists.txt index 0d22047a3..26943a769 100644 --- a/python/sglang/kernels/aot/CMakeLists.txt +++ b/python/sglang/kernels/aot/CMakeLists.txt @@ -20,7 +20,8 @@ set(GITHUB_ARTIFACTORY "github.com" CACHE STRING "GitHub mirror URL") find_package(Python COMPONENTS Interpreter Development.Module ${SKBUILD_SABI_COMPONENT} REQUIRED) # CXX -set(CMAKE_CXX_STANDARD 17) +set(SGL_KERNEL_CXX_STANDARD "17" CACHE STRING "C++ standard used for host and CUDA compilation") +set(CMAKE_CXX_STANDARD ${SGL_KERNEL_CXX_STANDARD}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") # CUDA @@ -125,7 +126,7 @@ set(SGL_KERNEL_CUDA_FLAGS "-Xcompiler" "-fPIC" "-gencode=arch=compute_90,code=sm_90" - "-std=c++17" + "-std=c++${SGL_KERNEL_CXX_STANDARD}" "-DFLASHINFER_ENABLE_F16" "-DCUTE_USE_PACKED_TUPLE=1" "-DCUTLASS_ENABLE_TENSOR_CORE_MMA=1" @@ -399,7 +400,7 @@ if (SGL_KERNEL_ENABLE_FA3) "-Xcompiler" "-fPIC" "-gencode=arch=compute_90a,code=sm_90a" - "-std=c++17" + "-std=c++${SGL_KERNEL_CXX_STANDARD}" "-DCUTE_USE_PACKED_TUPLE=1" "-DCUTLASS_ENABLE_TENSOR_CORE_MMA=1" "-DCUTLASS_VERSIONS_GENERATED" @@ -493,7 +494,7 @@ endif() set(INFLLM_FLASH_CUDA_FLAGS "-DNDEBUG" "-O3" - "-std=c++17" + "-std=c++${SGL_KERNEL_CXX_STANDARD}" "-Xcompiler" "-fPIC" "-U__CUDA_NO_HALF_OPERATORS__" diff --git a/python/sglang/kernels/aot/cmake/flashmla.cmake b/python/sglang/kernels/aot/cmake/flashmla.cmake index 11d5380d9..5b4decca3 100644 --- a/python/sglang/kernels/aot/cmake/flashmla.cmake +++ b/python/sglang/kernels/aot/cmake/flashmla.cmake @@ -2,8 +2,8 @@ # sm90 dense decode HEAD_DIM_K=512 support (sgl-project/FlashMLA#9, merged). FetchContent_Declare( repo-flashmla - URL https://${GITHUB_ARTIFACTORY}/sgl-project/FlashMLA/archive/05e26647fe840b8baedae486c2d86d5ce4efeb7c.tar.gz - URL_HASH SHA256=ce369489bbfc42cdfbba9aa949de0270e64469d530748dea9f4f60b3c69dea9b + URL https://${GITHUB_ARTIFACTORY}/sgl-project/FlashMLA/archive/c1dee569a494b184811a08171a690ece21420262.tar.gz + URL_HASH SHA256=77d3f1714b5903dc8f7a99fbc3a5d9a2b886e449f994b6c4b1d2feeacb467b1e ) FetchContent_Populate(repo-flashmla)