diff --git a/jax/training/0.10.0/Dockerfile.neuronx b/jax/training/0.10.0/Dockerfile.neuronx index 9d6368e..dfbc394 100644 --- a/jax/training/0.10.0/Dockerfile.neuronx +++ b/jax/training/0.10.0/Dockerfile.neuronx @@ -1,14 +1,14 @@ ARG BUILD_STAGE=prod -FROM public.ecr.aws/docker/library/ubuntu:24.04 AS base +FROM public.ecr.aws/docker/library/ubuntu:26.04 AS base LABEL dlc_major_version="1" LABEL maintainer="Amazon AI" -# This arg required to stop docker build waiting for region configuration while installing tz data from ubuntu 24 +# Keep apt non-interactive so tzdata's timezone/region prompt can't stall the build ARG DEBIAN_FRONTEND=noninteractive -ARG PYTHON=python3.13 -ARG PYTHON_VERSION=3.13.13 +ARG PYTHON=python3.14 +ARG PYTHON_VERSION=3.14.7 ARG PIP=pip3 ARG OMPI_VERSION=4.1.5 ARG PYPI_SIMPLE_URL="https://pypi.org/simple/" @@ -112,9 +112,9 @@ RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2 && ./aws/install \ && rm -rf awscliv2.zip aws -# U24 will not allow installation of pip packages outside of venv without this flag -# This is because U24 ships with Python 3.12 by default and installation into the Python -# interpreter’s directory are disabled outside of a virtual environment. +# This image installs pip packages into the base interpreter (no venv). Ubuntu 26 — like 24 — +# ships its system Python as an externally-managed environment (PEP 668), which blocks that, so +# set the flag to allow it. (Interpreter here is the source-built Python 3.14 in /usr/local.) # https://peps.python.org/pep-0668/ RUN ${PIP} config set global.break-system-packages true @@ -160,37 +160,50 @@ RUN HOME_DIR=/root \ # Setting up APT and PIP repo for neuron artifacts ARG NEURON_APT_REPO=apt.repos.neuron.amazonaws.com -ARG NEURON_APT_REPO_KEY ARG NEURON_PIP_REPO=pip.repos.neuron.amazonaws.com -ARG NEURON_PIP_REPO_KEY -RUN mkdir -p /etc/apt/keyrings \ - && APT_REPO_PREFIX=$([ -n "${NEURON_APT_REPO_KEY}" ] && echo "${NEURON_APT_REPO_KEY}@" || echo "") \ - && echo "deb [signed-by=/etc/apt/keyrings/neuron.gpg] https://${APT_REPO_PREFIX}${NEURON_APT_REPO} jammy main" > /etc/apt/sources.list.d/neuron.list \ - && curl $([ -n "${NEURON_APT_REPO_KEY}" ] && echo "-u ${NEURON_APT_REPO_KEY}") --retry 3 --retry-delay 1 --retry-all-errors -fSL "https://${NEURON_APT_REPO}/GPG-PUB-KEY-AMAZON-AWS-NEURON.PUB" | gpg --dearmor > /etc/apt/keyrings/neuron.gpg +RUN --mount=type=secret,id=neuron_repo \ + mkdir -p /etc/apt/keyrings \ + && echo "deb [signed-by=/etc/apt/keyrings/neuron.gpg] https://${NEURON_APT_REPO} jammy main" > /etc/apt/sources.list.d/neuron.list \ + && NEURON_REPO_CRED="$([ -s /run/secrets/neuron_repo ] && cat /run/secrets/neuron_repo || true)" \ + && curl $([ -n "${NEURON_REPO_CRED}" ] && echo "-u ${NEURON_REPO_CRED}") --retry 3 --retry-delay 1 --retry-all-errors -fSL "https://${NEURON_APT_REPO}/GPG-PUB-KEY-AMAZON-AWS-NEURON.PUB" | gpg --dearmor > /etc/apt/keyrings/neuron.gpg # Neuron SDK components version numbers -ARG NEURONX_RUNTIME_LIB_VERSION=2.34.10.0-ac18d186d -ARG NEURONX_COLLECTIVES_LIB_VERSION=2.34.10.0-74eaafac6 -ARG NEURONX_TOOLS_VERSION=2.32.28.0-526c2b7f6 +ARG NEURONX_RUNTIME_LIB_VERSION=2.35.30.0-d2725ccb8 +ARG NEURONX_COLLECTIVES_LIB_VERSION=2.35.43.0-354ad3064 +ARG NEURONX_TOOLS_VERSION=2.33.38.0-f874d5618 -ARG NEURONX_CC_VERSION=2.27.5334.0+f702b353 -ARG NEURONX_JAX_TRAINING_VERSION=0.10.0.1.0.11459+1e1fc1db -ARG NKI_VERSION=0.6.0+31049202112.g85070674 -ARG NEURON_AGENTIC_DEVELOPMENT_VERSION=1.3 +ARG NEURONX_CC_VERSION=2.28.7631.0+8f7b0cf5 +ARG NEURONX_JAX_TRAINING_VERSION=0.10.0.1.0.14198+40d442c2 +ARG NKI_VERSION=0.7.0+37713544100.gfede04bb +ARG NEURON_AGENTIC_DEVELOPMENT_VERSION=1.4 FROM base AS repo # Install Neuron components from the apt and pip repos (latest versions) -RUN apt-get update \ +RUN --mount=type=secret,id=neuron_repo \ + mkdir -p /etc/apt/auth.conf.d \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + printf 'machine %s login %s password %s\n' "${NEURON_APT_REPO}" "${CRED%%:*}" "${CRED#*:}" > /etc/apt/auth.conf.d/neuron.conf; \ + chmod 600 /etc/apt/auth.conf.d/neuron.conf; \ + fi \ + && apt-get update \ && apt-get install -y \ aws-neuronx-tools \ aws-neuronx-collectives \ aws-neuronx-runtime-lib \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /tmp/tmp* \ - && apt-get clean + && apt-get clean \ + && rm -f /etc/apt/auth.conf.d/neuron.conf -RUN PIP_REPO_URL=$([ -n "${NEURON_PIP_REPO_KEY}" ] && echo "https://${NEURON_PIP_REPO_KEY}@${NEURON_PIP_REPO}" || echo "https://${NEURON_PIP_REPO}") \ +RUN --mount=type=secret,id=neuron_repo \ + PIP_REPO_URL="https://${NEURON_PIP_REPO}" \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + ENC="$(printf '%s' "$CRED" | python3 -c 'import urllib.parse,sys; u,p=sys.stdin.read().split(":",1); print(urllib.parse.quote(u,safe="")+":"+urllib.parse.quote(p,safe=""))')"; \ + PIP_REPO_URL="https://${ENC}@${NEURON_PIP_REPO}"; \ + fi \ && ${PIP} install --no-cache-dir --force-reinstall \ --index-url ${PIP_REPO_URL} \ --extra-index-url ${PYPI_SIMPLE_URL} \ @@ -203,19 +216,31 @@ RUN PIP_REPO_URL=$([ -n "${NEURON_PIP_REPO_KEY}" ] && echo "https://${NEURON_PIP FROM base AS prod -# Install Neuron components -# Install Neuron Driver, Runtime and Tools -RUN apt-get update \ +# Install Neuron components from the apt and pip repos +RUN --mount=type=secret,id=neuron_repo \ + mkdir -p /etc/apt/auth.conf.d \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + printf 'machine %s login %s password %s\n' "${NEURON_APT_REPO}" "${CRED%%:*}" "${CRED#*:}" > /etc/apt/auth.conf.d/neuron.conf; \ + chmod 600 /etc/apt/auth.conf.d/neuron.conf; \ + fi \ + && apt-get update \ && apt-get install -y \ aws-neuronx-tools=$NEURONX_TOOLS_VERSION \ aws-neuronx-collectives=$NEURONX_COLLECTIVES_LIB_VERSION \ aws-neuronx-runtime-lib=$NEURONX_RUNTIME_LIB_VERSION \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /tmp/tmp* \ - && apt-get clean + && apt-get clean \ + && rm -f /etc/apt/auth.conf.d/neuron.conf -# Install JAX & Neuron CC -RUN PIP_REPO_URL=$([ -n "${NEURON_PIP_REPO_KEY}" ] && echo "https://${NEURON_PIP_REPO_KEY}@${NEURON_PIP_REPO}" || echo "https://${NEURON_PIP_REPO}") \ +RUN --mount=type=secret,id=neuron_repo \ + PIP_REPO_URL="https://${NEURON_PIP_REPO}" \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + ENC="$(printf '%s' "$CRED" | python3 -c 'import urllib.parse,sys; u,p=sys.stdin.read().split(":",1); print(urllib.parse.quote(u,safe="")+":"+urllib.parse.quote(p,safe=""))')"; \ + PIP_REPO_URL="https://${ENC}@${NEURON_PIP_REPO}"; \ + fi \ && ${PIP} install --no-cache-dir --force-reinstall \ --index-url ${PIP_REPO_URL} \ --trusted-host ${NEURON_PIP_REPO} \ @@ -229,7 +254,8 @@ RUN PIP_REPO_URL=$([ -n "${NEURON_PIP_REPO_KEY}" ] && echo "https://${NEURON_PIP FROM ${BUILD_STAGE} AS final # Upgrade OS packages to latest versions -RUN apt-get update \ +RUN rm -f /etc/apt/sources.list.d/neuron.list /etc/apt/keyrings/neuron.gpg \ + && apt-get update \ && apt-get upgrade -y \ && rm -rf /var/lib/apt/lists/* \ && apt-get clean diff --git a/pytorch/torch-neuronx/2.14.0/Dockerfile.neuronx b/pytorch/torch-neuronx/2.14.0/Dockerfile.neuronx new file mode 100644 index 0000000..c75be9d --- /dev/null +++ b/pytorch/torch-neuronx/2.14.0/Dockerfile.neuronx @@ -0,0 +1,354 @@ +ARG BUILD_STAGE=prod + +FROM public.ecr.aws/docker/library/ubuntu:26.04 AS base + +LABEL maintainer="Amazon AI" +LABEL dlc_major_version="1" + +ARG PYTHON=python3.14 +ARG PYTHON_VERSION=3.14.7 +ARG PIP=pip3 +ARG OMPI_VERSION=4.1.5 +ARG PYPI_SIMPLE_URL="https://pypi.org/simple/" + +# Keep apt non-interactive so tzdata's timezone/region prompt can't stall the build +ARG DEBIAN_FRONTEND=noninteractive + +# Python won’t try to write .pyc or .pyo files on the import of source modules +# Force stdin, stdout and stderr to be totally unbuffered. Good for logging +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 +ENV PYTHONIOENCODING=UTF-8 +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 +ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/aws/neuron/lib" +ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/amazon/efa/lib" +ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/amazon/efa/lib64" +ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/amazon/openmpi/lib64" +ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/local/lib" +ENV PATH="/opt/aws/neuron/bin:${PATH}" +ENV PATH="${PATH}:/opt/amazon/efa/bin" +ENV SAGEMAKER_TRAINING_MODULE=sagemaker_pytorch_container.training:main +ENV DGLBACKEND=pytorch + +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + cmake \ + curl \ + git \ + gnupg2 \ + gpg-agent \ + jq \ + libglib2.0-0 \ + libgl1-mesa-dri \ + libsm6 \ + libxext6 \ + libxrender-dev \ + libssl-dev \ + libsqlite3-dev \ + libgdbm-dev \ + libgdbm-compat-dev \ + libc6-dev \ + libbz2-dev \ + liblzma-dev \ + libncurses-dev \ + libreadline-dev \ + libffi-dev \ + libcap-dev \ + libhwloc-dev \ + openssl \ + patchelf \ + software-properties-common \ + tk-dev \ + unzip \ + wget \ + zlib1g-dev \ + libzstd-dev \ + && rm -rf /tmp/tmp* \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +# Install Open MPI +RUN mkdir -p /tmp/openmpi \ + && cd /tmp/openmpi \ + && wget --quiet https://download.open-mpi.org/release/open-mpi/v4.1/openmpi-${OMPI_VERSION}.tar.gz \ + && tar zxf openmpi-${OMPI_VERSION}.tar.gz \ + && cd openmpi-${OMPI_VERSION} \ + && ./configure --enable-orterun-prefix-by-default \ + && make -j $(nproc) all \ + && make install \ + && ldconfig \ + && rm -rf /tmp/openmpi + + # Install packages an configure SSH for MPI in K8s +RUN apt-get update && apt-get install -y openmpi-bin openssh-server \ + && mkdir -p /var/run/sshd \ + && echo " UserKnownHostsFile /dev/null" >> /etc/ssh/ssh_config \ + && echo " StrictHostKeyChecking no" >> /etc/ssh/ssh_config \ + && sed -i 's/#\(StrictModes \).*/\1no/g' /etc/ssh/sshd_config \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/tmp* \ + && apt-get clean + + + # Install Python +RUN wget -q https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tgz \ + && tar -xzf Python-$PYTHON_VERSION.tgz \ + && cd Python-$PYTHON_VERSION \ + && ./configure --enable-shared --prefix=/usr/local \ + && make -j $(nproc) && make install \ + && cd .. && rm -rf ../Python-$PYTHON_VERSION* \ + && ln -s /usr/local/bin/pip3 /usr/bin/pip \ + && ln -s /usr/local/bin/$PYTHON /usr/local/bin/python \ + && ${PIP} --no-cache-dir install --upgrade pip \ + && rm -rf ~/.cache/pip/* + +WORKDIR / + +# The ENV variables declared below are changed in the previous section +# Grouping these ENV variables in the first section causes +# ompi_info to fail. This is only observed in CPU containers +ENV PATH="$PATH:/home/.openmpi/bin" +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/.openmpi/lib/" +RUN ompi_info --parsable --all | grep mpi_built_with_cuda_support:value + +# Install AWS CLI +RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ + && unzip awscliv2.zip \ + && ./aws/install \ + && rm -rf awscliv2.zip aws + +RUN ${PIP} install --no-cache-dir -U \ + scipy \ + click \ + cryptography \ + psutil \ + dataset \ + Pillow \ + uv \ + && rm -rf ~/.cache/pip/* + +RUN mkdir -p /etc/pki/tls/certs && cp /etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt + +RUN ${PIP} install --no-cache-dir -U \ + attrs \ + python-etcd \ + requests \ + && rm -rf ~/.cache/pip/* + +# EFA Installer does apt get. Make sure to run apt update before that +RUN apt-get update \ + && cd $HOME \ + && curl -O https://efa-installer.amazonaws.com/aws-efa-installer-latest.tar.gz \ + && wget https://efa-installer.amazonaws.com/aws-efa-installer.key && gpg --import aws-efa-installer.key \ + && cat aws-efa-installer.key | gpg --fingerprint \ + && wget https://efa-installer.amazonaws.com/aws-efa-installer-latest.tar.gz.sig && gpg --verify ./aws-efa-installer-latest.tar.gz.sig \ + && tar -xf aws-efa-installer-latest.tar.gz \ + && cd aws-efa-installer \ + && ./efa_installer.sh -y -g --skip-kmod --skip-limit-conf --no-verify \ + && cd $HOME \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/tmp* \ + && apt-get clean + +# Install some common packages used by training scripts +# Needed for running bert training scripts +RUN pip3 install --no-cache-dir -U \ + graphviz \ + tensorboard \ + accelerate \ + && rm -rf ~/.cache/pip/* + +# Copy workaround script for incorrect hostname +COPY changehostname.c / +COPY --chmod=755 start_with_right_hostname.sh deep_learning_container.py /usr/local/bin/ + +RUN HOME_DIR=/root \ + && curl -o ${HOME_DIR}/oss_compliance.zip https://aws-dlinfra-utilities.s3.amazonaws.com/oss_compliance.zip \ + && unzip ${HOME_DIR}/oss_compliance.zip -d ${HOME_DIR}/ \ + && cp ${HOME_DIR}/oss_compliance/test/testOSSCompliance /usr/local/bin/testOSSCompliance \ + && chmod +x /usr/local/bin/testOSSCompliance \ + && chmod +x ${HOME_DIR}/oss_compliance/generate_oss_compliance.sh \ + && ${HOME_DIR}/oss_compliance/generate_oss_compliance.sh ${HOME_DIR} ${PYTHON} \ + && rm -rf ${HOME_DIR}/oss_compliance* \ + && rm -rf /tmp/tmp* + +RUN curl -o /license.txt https://aws-dlc-licenses.s3.amazonaws.com/pytorch-2.14/license.txt + +# Setting up APT and PIP repo for neuron artifacts +ARG NEURON_APT_REPO=apt.repos.neuron.amazonaws.com +ARG NEURON_PIP_REPO=pip.repos.neuron.amazonaws.com +RUN --mount=type=secret,id=neuron_repo \ + mkdir -p /etc/apt/keyrings \ + && echo "deb [signed-by=/etc/apt/keyrings/neuron.gpg] https://${NEURON_APT_REPO} jammy main" > /etc/apt/sources.list.d/neuron.list \ + && NEURON_REPO_CRED="$([ -s /run/secrets/neuron_repo ] && cat /run/secrets/neuron_repo || true)" \ + && curl $([ -n "${NEURON_REPO_CRED}" ] && echo "-u ${NEURON_REPO_CRED}") --retry 3 --retry-delay 1 --retry-all-errors -fSL "https://${NEURON_APT_REPO}/GPG-PUB-KEY-AMAZON-AWS-NEURON.PUB" | gpg --dearmor > /etc/apt/keyrings/neuron.gpg + +# Neuron SDK components +ARG NEURONX_COLLECTIVES_LIB_VERSION=2.35.43.0-354ad3064 +ARG NEURONX_RUNTIME_LIB_VERSION=2.35.30.0-d2725ccb8 +ARG NEURONX_TOOLS_VERSION=2.33.38.0-f874d5618 + +ARG NEURONX_CC_VERSION=2.28.7631.0+8f7b0cf5 +ARG NKI_VERSION=0.7.0+37713544100.gfede04bb +ARG NEURON_AGENTIC_DEVELOPMENT_VERSION=1.4 + +# Primary repo: torch-neuronx +ARG GITHUB_REPO=https://github.com/aws-neuron/torch-neuronx.git +ARG GITHUB_REPO_BRANCH=release-2.33 + +# Secondary repo: torchtitan-neuron +ARG GITHUB_REPO_2=https://github.com/aws-neuron/torchtitan-neuron.git +ARG GITHUB_REPO_BRANCH_2=release_2.33.0 + +# Configure SSH access +RUN mkdir -p /root/.ssh \ + && echo "StrictHostKeyChecking no" >> /root/.ssh/config \ + && ssh-keyscan -t rsa github.com >> /root/.ssh/known_hosts + +# Clone torch-neuronx repository, install Bazelisk, and make build scripts executable +RUN --mount=type=secret,id=containers_github_ssh_key,target=/root/.ssh/id_ed25519,mode=0600 \ + git clone -b ${GITHUB_REPO_BRANCH} ${GITHUB_REPO} /workspace/torch_neuronx \ + && bash /workspace/torch_neuronx/install_bazelisk.sh \ + && chmod +x /workspace/torch_neuronx/tools/* + +# Clone torchtitan-neuron repository (secondary repo) +RUN --mount=type=secret,id=containers_github_ssh_key,target=/root/.ssh/id_ed25519,mode=0600 \ + git clone -b ${GITHUB_REPO_BRANCH_2} ${GITHUB_REPO_2} /workspace/torchtitan_neuron + +FROM base AS repo + +# Install Neuron components from the apt repos (latest versions). +RUN --mount=type=secret,id=neuron_repo \ + mkdir -p /etc/apt/auth.conf.d \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + printf 'machine %s login %s password %s\n' "${NEURON_APT_REPO}" "${CRED%%:*}" "${CRED#*:}" > /etc/apt/auth.conf.d/neuron.conf; \ + chmod 600 /etc/apt/auth.conf.d/neuron.conf; \ + fi \ + && apt-get update \ + && apt-get install -y \ + aws-neuronx-tools \ + aws-neuronx-collectives \ + aws-neuronx-runtime-lib \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/tmp* \ + && apt-get clean \ + && rm -f /etc/apt/auth.conf.d/neuron.conf + +# Install Neuron pip components (latest versions) and build torch-neuronx from source. +RUN --mount=type=secret,id=neuron_repo \ + PIP_REPO_URL="https://${NEURON_PIP_REPO}" \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + ENC="$(printf '%s' "$CRED" | python3 -c 'import urllib.parse,sys; u,p=sys.stdin.read().split(":",1); print(urllib.parse.quote(u,safe="")+":"+urllib.parse.quote(p,safe=""))')"; \ + PIP_REPO_URL="https://${ENC}@${NEURON_PIP_REPO}"; \ + fi \ + && cd /workspace/torch_neuronx \ + && ${PIP} install --no-cache-dir --force-reinstall \ + --index-url ${PIP_REPO_URL} \ + --trusted-host ${NEURON_PIP_REPO} \ + --extra-index-url ${PYPI_SIMPLE_URL} \ + neuronx-cc \ + nki \ + neuron_agentic_development \ + -e . \ + && ./tools/build --python "${PYTHON#python}" \ + && rm -rf ~/.cache/pip/* + +# Pin torch to the version torch-neuronx was just built against for all later pip installs +# in this image (prevents an unconstrained dep, e.g. torchdata, from upgrading torch). +RUN mkdir -p /etc/pip \ + && ${PIP} freeze | grep -E '^torch==' > /etc/pip/constraints.txt +ENV PIP_CONSTRAINT=/etc/pip/constraints.txt + +# Editable-install TorchTitan into the DLC's torch-neuronx env, resolving its declared +# dependencies from the configured indexes. +RUN cd /workspace/torchtitan_neuron \ + && ${PIP} install --no-cache-dir -e . \ + && rm -rf ~/.cache/pip/* + +FROM base AS prod + +# Install Neuron apt components with specific versions. +RUN --mount=type=secret,id=neuron_repo \ + mkdir -p /etc/apt/auth.conf.d \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + printf 'machine %s login %s password %s\n' "${NEURON_APT_REPO}" "${CRED%%:*}" "${CRED#*:}" > /etc/apt/auth.conf.d/neuron.conf; \ + chmod 600 /etc/apt/auth.conf.d/neuron.conf; \ + fi \ + && apt-get update \ + && apt-get install -y \ + aws-neuronx-tools=$NEURONX_TOOLS_VERSION \ + aws-neuronx-collectives=$NEURONX_COLLECTIVES_LIB_VERSION \ + aws-neuronx-runtime-lib=$NEURONX_RUNTIME_LIB_VERSION \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/tmp* \ + && apt-get clean \ + && rm -f /etc/apt/auth.conf.d/neuron.conf + +# Install Neuron pip components with specific versions and build torch-neuronx from source. +RUN --mount=type=secret,id=neuron_repo \ + PIP_REPO_URL="https://${NEURON_PIP_REPO}" \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + ENC="$(printf '%s' "$CRED" | python3 -c 'import urllib.parse,sys; u,p=sys.stdin.read().split(":",1); print(urllib.parse.quote(u,safe="")+":"+urllib.parse.quote(p,safe=""))')"; \ + PIP_REPO_URL="https://${ENC}@${NEURON_PIP_REPO}"; \ + fi \ + && cd /workspace/torch_neuronx \ + && ${PIP} install --no-cache-dir --force-reinstall \ + --index-url ${PIP_REPO_URL} \ + --trusted-host ${NEURON_PIP_REPO} \ + --extra-index-url ${PYPI_SIMPLE_URL} \ + neuronx-cc==$NEURONX_CC_VERSION \ + nki==$NKI_VERSION \ + neuron_agentic_development==$NEURON_AGENTIC_DEVELOPMENT_VERSION \ + -e . \ + && ./tools/build --python "${PYTHON#python}" \ + && rm -rf ~/.cache/pip/* + +# Pin torch to the version torch-neuronx was just built against for all later pip installs +# in this image (prevents an unconstrained dep, e.g. torchdata, from upgrading torch). +RUN mkdir -p /etc/pip \ + && ${PIP} freeze | grep -E '^torch==' > /etc/pip/constraints.txt +ENV PIP_CONSTRAINT=/etc/pip/constraints.txt + +# Editable-install TorchTitan into the DLC's torch-neuronx env, resolving its declared +# dependencies from the configured indexes. +RUN cd /workspace/torchtitan_neuron \ + && ${PIP} install --no-cache-dir -e . \ + && rm -rf ~/.cache/pip/* + + +FROM ${BUILD_STAGE} AS final + +# Prune build caches, development-only files, and VCS metadata. +RUN rm -rf \ + /root/.cache/bazel \ + /root/.cache/bazel-torch-neuronx \ + /root/.cache/uv \ + /workspace/torch_neuronx/.venv \ + /workspace/torch_neuronx/uv.lock \ + /workspace/torch_neuronx/.github \ + /workspace/torch_neuronx/.internal_docs \ + /workspace/torchtitan_neuron/.github \ + && find /workspace/torch_neuronx -depth -type d -name .git -exec rm -rf {} + 2>/dev/null || true \ + && find /workspace/torchtitan_neuron -depth -type d -name .git -exec rm -rf {} + 2>/dev/null || true \ + && find /workspace/torch_neuronx -name 'requirements*.txt' -delete 2>/dev/null || true + +# Upgrade OS packages to latest versions +RUN rm -f /etc/apt/sources.list.d/neuron.list /etc/apt/keyrings/neuron.gpg \ + && apt-get update \ + && apt-get upgrade -y \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +# Starts framework +ENTRYPOINT ["bash", "-m", "start_with_right_hostname.sh"] +CMD ["/bin/bash"] + +HEALTHCHECK CMD curl --fail http://localhost:8080/ping || exit 1 \ No newline at end of file diff --git a/vllm-omni/inference/0.29.0.0.2.0/Dockerfile.neuronx b/vllm-omni/inference/0.29.0.0.2.0/Dockerfile.neuronx new file mode 100644 index 0000000..de4fbbe --- /dev/null +++ b/vllm-omni/inference/0.29.0.0.2.0/Dockerfile.neuronx @@ -0,0 +1,312 @@ +ARG BUILD_STAGE=prod + +FROM public.ecr.aws/docker/library/ubuntu:26.04 AS base + +LABEL dlc_major_version="1" +LABEL maintainer="Amazon AI" + +# Keep apt non-interactive so tzdata's timezone/region prompt can't stall the build +ARG DEBIAN_FRONTEND=noninteractive +ARG PIP=pip3 +ARG PYTHON=python3.13 +ARG PYTHON_VERSION=3.13.13 +ARG TORCHSERVE_VERSION=0.11.0 +ARG PYPI_SIMPLE_URL="https://pypi.org/simple/" + + +# See http://bugs.python.org/issue19846 +ENV LANG=C.UTF-8 +ENV LD_LIBRARY_PATH="/opt/aws/neuron/lib" +ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/amazon/efa/lib" +ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/amazon/efa/lib64" +ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/lib/x86_64-linux-gnu" +ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/conda/lib/" +ENV PATH=/opt/conda/bin:/opt/aws/neuron/bin:$PATH +ENV PATH="${PATH}:/opt/amazon/efa/bin" + +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y --no-install-recommends \ + apt-transport-https \ + build-essential \ + ca-certificates \ + cmake \ + curl \ + ffmpeg \ + gcc \ + git \ + gnupg2 \ + gpg-agent \ + jq \ + libgl1 \ + libgl1-mesa-dri \ + libglib2.0-0 \ + libsm6 \ + libxext6 \ + libxrender-dev \ + libcap-dev \ + libhwloc-dev \ + openssh-client \ + openjdk-11-jdk \ + unzip \ + wget \ + zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/tmp* \ + && apt-get clean + + +# https://github.com/docker-library/openjdk/issues/261 https://github.com/docker-library/openjdk/pull/263/files +RUN keytool -importkeystore -srckeystore /etc/ssl/certs/java/cacerts -destkeystore /etc/ssl/certs/java/cacerts.jks -deststoretype JKS -srcstorepass changeit -deststorepass changeit -noprompt; \ + mv /etc/ssl/certs/java/cacerts.jks /etc/ssl/certs/java/cacerts; \ + /var/lib/dpkg/info/ca-certificates-java.postinst configure; + +RUN curl -L -o ~/miniforge.sh https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh \ + && chmod +x ~/miniforge.sh \ + && ~/miniforge.sh -b -p /opt/conda \ + && rm ~/miniforge.sh \ + && /opt/conda/bin/mamba install -c conda-forge -y \ + python=$PYTHON_VERSION \ + pyopenssl \ + cython \ + mkl-include \ + mkl \ + parso \ + # Below 2 are included in miniconda base, but not mamba so need to install + conda-content-trust \ + charset-normalizer \ + && /opt/conda/bin/conda clean -ya + +RUN /opt/conda/bin/mamba install -c conda-forge \ + python=$PYTHON_VERSION \ + scikit-learn \ + h5py \ + requests \ + && conda clean -ya \ + && pip install --upgrade pip \ + --trusted-host pypi.org --trusted-host files.pythonhosted.org \ + && ln -s /opt/conda/bin/pip /usr/local/bin/pip3 \ + && pip install \ + enum-compat \ + ipython \ + && rm -rf ~/.cache/pip/* + +# Install EFA +RUN apt-get update \ + && cd $HOME \ + && curl -O https://efa-installer.amazonaws.com/aws-efa-installer-latest.tar.gz \ + && wget https://efa-installer.amazonaws.com/aws-efa-installer.key && gpg --import aws-efa-installer.key \ + && cat aws-efa-installer.key | gpg --fingerprint \ + && wget https://efa-installer.amazonaws.com/aws-efa-installer-latest.tar.gz.sig && gpg --verify ./aws-efa-installer-latest.tar.gz.sig \ + && tar -xf aws-efa-installer-latest.tar.gz \ + && cd aws-efa-installer \ + && ./efa_installer.sh -y -g --skip-kmod --skip-limit-conf --no-verify \ + && cd $HOME \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/tmp* \ + && apt-get clean + +# Stub libcuda.so.1 so the NIXL LIBFABRIC backend can dlopen on Neuron (no CUDA driver present). +# The plugin references three CUDA *driver* entrypoints only for an optional GPUDirect path that +# is never exercised on Neuron; defining them as no-ops satisfies RTLD_NOW without a real driver. +RUN printf '%s\n' \ + 'int cuCtxSetCurrent(void* c){return 999;}' \ + 'int cuDeviceGetPCIBusId(char* s, int n, int d){return 999;}' \ + 'int cuPointerGetAttributes(void* a, void* b, unsigned long long p){return 999;}' \ + > /tmp/cuda_stub.c \ + && gcc -shared -fPIC -Wl,-soname,libcuda.so.1 -o /usr/local/lib/libcuda.so.1 /tmp/cuda_stub.c \ + && rm -f /tmp/cuda_stub.c \ + && ldconfig + +COPY --chmod=755 vllm_entrypoint.py neuron-monitor.sh deep_learning_container.py /usr/local/bin/ + +# SageMaker hosting support. SageMaker launches an inference container as +# `docker run serve`, so exposing an executable named `serve` on PATH lets the +# existing ENTRYPOINT (vllm_entrypoint.py, which execs its argv) start the vLLM server. +COPY --chmod=755 serve.sh /usr/local/bin/serve +COPY --chmod=755 sagemaker_args.py /usr/local/bin/sagemaker_args.py + +### Mount Point ### +# When launching the container, mount the code directory to /workspace +ARG APP_MOUNT=/workspace +VOLUME ${APP_MOUNT} +WORKDIR ${APP_MOUNT}/vllm + +# Install AWS CLI +RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ + && unzip awscliv2.zip \ + && ./aws/install \ + && rm -rf awscliv2.zip aws + +RUN ${PIP} install --no-cache-dir -U \ + "opencv-python" \ + "pandas" \ + "boto3" \ + "cryptography" \ + "pytest" \ + "wheel" \ + "jinja2" \ + uv \ + torchserve==${TORCHSERVE_VERSION} \ + torch-model-archiver==${TORCHSERVE_VERSION} \ + && rm -rf ~/.cache/pip/* + +RUN useradd -m model-server \ + && mkdir -p /home/model-server/tmp /opt/ml/model \ + && chown -R model-server /home/model-server /opt/ml/model +COPY config.properties /home/model-server + +# Compliance +RUN HOME_DIR=/root \ + && curl -o ${HOME_DIR}/oss_compliance.zip https://aws-dlinfra-utilities.s3.amazonaws.com/oss_compliance.zip \ + && unzip ${HOME_DIR}/oss_compliance.zip -d ${HOME_DIR}/ \ + && cp ${HOME_DIR}/oss_compliance/test/testOSSCompliance /usr/local/bin/testOSSCompliance \ + && chmod +x /usr/local/bin/testOSSCompliance \ + && chmod +x ${HOME_DIR}/oss_compliance/generate_oss_compliance.sh \ + && ${HOME_DIR}/oss_compliance/generate_oss_compliance.sh ${HOME_DIR} ${PYTHON} \ + && rm -rf ${HOME_DIR}/oss_compliance* \ + # conda leaves an empty /root/.cache/conda/notices.cache file which is not removed by conda clean -ya + && rm -rf ${HOME_DIR}/.cache/conda + +# Setting up APT and PIP repo for neuron artifacts +ARG NEURON_APT_REPO=apt.repos.neuron.amazonaws.com +ARG NEURON_PIP_REPO=pip.repos.neuron.amazonaws.com +RUN --mount=type=secret,id=neuron_repo \ + mkdir -p /etc/apt/keyrings \ + && echo "deb [signed-by=/etc/apt/keyrings/neuron.gpg] https://${NEURON_APT_REPO} jammy main" > /etc/apt/sources.list.d/neuron.list \ + && NEURON_REPO_CRED="$([ -s /run/secrets/neuron_repo ] && cat /run/secrets/neuron_repo || true)" \ + && curl $([ -n "${NEURON_REPO_CRED}" ] && echo "-u ${NEURON_REPO_CRED}") --retry 3 --retry-delay 1 --retry-all-errors -fSL "https://${NEURON_APT_REPO}/GPG-PUB-KEY-AMAZON-AWS-NEURON.PUB" | gpg --dearmor > /etc/apt/keyrings/neuron.gpg + +# Neuron SDK components version numbers +ARG NEURONX_COLLECTIVES_LIB_VERSION=2.35.43.0-354ad3064 +ARG NEURONX_RUNTIME_LIB_VERSION=2.35.30.0-d2725ccb8 +ARG NEURONX_TOOLS_VERSION=2.33.38.0-f874d5618 + +ARG NEURONX_CC_VERSION=2.28.7631.0+8f7b0cf5 +ARG NKI_VERSION=0.7.0+37713544100.gfede04bb +ARG NEURON_AGENTIC_DEVELOPMENT_VERSION=1.4 +ARG LIBTORCH_NEURONX_LITE_VERSION=2.13.0.1.0.3112+653bc48f + +# Primary repo: vllm-omni-neuron +ARG GITHUB_REPO=https://github.com/aws-neuron/vllm-omni-neuron.git +ARG GITHUB_REPO_BRANCH=release-0.29.0.0.2.0 + +# Secondary repo: vllm-neuron +ARG GITHUB_REPO_2=https://github.com/vllm-project/vllm-neuron.git +ARG GITHUB_REPO_BRANCH_2=release-0.29.0.1.2.0 + +# Configure SSH access +RUN mkdir -p /root/.ssh \ + && echo "StrictHostKeyChecking no" >> /root/.ssh/config \ + && ssh-keyscan -t rsa github.com >> /root/.ssh/known_hosts + +# Clone vllm-omni-neuron repository +RUN --mount=type=secret,id=containers_github_ssh_key,target=/root/.ssh/id_ed25519,mode=0600 \ + git clone -b ${GITHUB_REPO_BRANCH} ${GITHUB_REPO} /opt/vllm-omni-neuron + +# Clone vllm-neuron repository +RUN --mount=type=secret,id=containers_github_ssh_key,target=/root/.ssh/id_ed25519,mode=0600 \ + git clone -b ${GITHUB_REPO_BRANCH_2} ${GITHUB_REPO_2} /opt/vllm-neuron + +FROM base AS repo + + +# Install Neuron components from the apt and pip repos (latest versions) +RUN --mount=type=secret,id=neuron_repo \ + mkdir -p /etc/apt/auth.conf.d \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + printf 'machine %s login %s password %s\n' "${NEURON_APT_REPO}" "${CRED%%:*}" "${CRED#*:}" > /etc/apt/auth.conf.d/neuron.conf; \ + chmod 600 /etc/apt/auth.conf.d/neuron.conf; \ + fi \ + && apt-get update \ + && apt-get install -y \ + aws-neuronx-tools \ + aws-neuronx-collectives \ + aws-neuronx-runtime-lib \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/tmp* \ + && apt-get clean \ + && rm -f /etc/apt/auth.conf.d/neuron.conf + +RUN --mount=type=secret,id=neuron_repo \ + PIP_REPO_URL="https://${NEURON_PIP_REPO}" \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + ENC="$(printf '%s' "$CRED" | python3 -c 'import urllib.parse,sys; u,p=sys.stdin.read().split(":",1); print(urllib.parse.quote(u,safe="")+":"+urllib.parse.quote(p,safe=""))')"; \ + PIP_REPO_URL="https://${ENC}@${NEURON_PIP_REPO}"; \ + fi \ + && ${PIP} install --no-cache-dir \ + --index-url ${PIP_REPO_URL} \ + --trusted-host ${NEURON_PIP_REPO} \ + --extra-index-url ${PYPI_SIMPLE_URL} \ + neuronx-cc \ + nki \ + neuron_agentic_development \ + libtorch-neuronx-lite \ + /opt/vllm-omni-neuron \ + /opt/vllm-omni-neuron/stubs/cosmos-guardrail \ + /opt/vllm-neuron \ + && rm -rf ~/.cache/pip/* + +FROM base AS prod + +# Install Neuron components with specific versions +RUN --mount=type=secret,id=neuron_repo \ + mkdir -p /etc/apt/auth.conf.d \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + printf 'machine %s login %s password %s\n' "${NEURON_APT_REPO}" "${CRED%%:*}" "${CRED#*:}" > /etc/apt/auth.conf.d/neuron.conf; \ + chmod 600 /etc/apt/auth.conf.d/neuron.conf; \ + fi \ + && apt-get update \ + && apt-get install -y \ + aws-neuronx-tools=$NEURONX_TOOLS_VERSION \ + aws-neuronx-collectives=$NEURONX_COLLECTIVES_LIB_VERSION \ + aws-neuronx-runtime-lib=$NEURONX_RUNTIME_LIB_VERSION \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/tmp* \ + && apt-get clean \ + && rm -f /etc/apt/auth.conf.d/neuron.conf + +RUN --mount=type=secret,id=neuron_repo \ + PIP_REPO_URL="https://${NEURON_PIP_REPO}" \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + ENC="$(printf '%s' "$CRED" | python3 -c 'import urllib.parse,sys; u,p=sys.stdin.read().split(":",1); print(urllib.parse.quote(u,safe="")+":"+urllib.parse.quote(p,safe=""))')"; \ + PIP_REPO_URL="https://${ENC}@${NEURON_PIP_REPO}"; \ + fi \ + && ${PIP} install --no-cache-dir \ + --index-url ${PIP_REPO_URL} \ + --trusted-host ${NEURON_PIP_REPO} \ + --extra-index-url ${PYPI_SIMPLE_URL} \ + neuronx-cc==$NEURONX_CC_VERSION \ + nki==$NKI_VERSION \ + neuron_agentic_development==$NEURON_AGENTIC_DEVELOPMENT_VERSION \ + libtorch-neuronx-lite==$LIBTORCH_NEURONX_LITE_VERSION \ + /opt/vllm-omni-neuron \ + /opt/vllm-omni-neuron/stubs/cosmos-guardrail \ + /opt/vllm-neuron \ + && rm -rf ~/.cache/pip/* + +FROM ${BUILD_STAGE} AS final + +# Upgrade OS packages to latest versions +RUN rm -f /etc/apt/sources.list.d/neuron.list /etc/apt/keyrings/neuron.gpg \ + && apt-get update \ + && apt-get upgrade -y \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +# Point conda at the libmamba solver, then remove the build-time rattler +# solver backend (not needed at runtime). +RUN conda config --set solver libmamba \ + && (conda remove -y --force-remove py-rattler conda-rattler-solver || true) \ + && conda clean -ya \ + && rm -rf /opt/conda/pkgs/* + +EXPOSE 8080 8081 + +ENTRYPOINT ["python", "/usr/local/bin/vllm_entrypoint.py"] +CMD ["/bin/bash"] +HEALTHCHECK CMD curl --fail http://localhost:8080/ping || exit 1 diff --git a/vllm/inference/0.29.0.1.2.0/Dockerfile.neuronx b/vllm/inference/0.29.0.1.2.0/Dockerfile.neuronx new file mode 100644 index 0000000..7ec4ce8 --- /dev/null +++ b/vllm/inference/0.29.0.1.2.0/Dockerfile.neuronx @@ -0,0 +1,300 @@ +ARG BUILD_STAGE=prod + +FROM public.ecr.aws/docker/library/ubuntu:26.04 AS base + +LABEL dlc_major_version="1" +LABEL maintainer="Amazon AI" + +# Keep apt non-interactive so tzdata's timezone/region prompt can't stall the build +ARG DEBIAN_FRONTEND=noninteractive +ARG PIP=pip3 +ARG PYTHON=python3.14 +ARG PYTHON_VERSION=3.14.7 +ARG TORCHSERVE_VERSION=0.11.0 +ARG PYPI_SIMPLE_URL="https://pypi.org/simple/" + + +# See http://bugs.python.org/issue19846 +ENV LANG=C.UTF-8 +ENV LD_LIBRARY_PATH="/opt/aws/neuron/lib" +ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/amazon/efa/lib" +ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/amazon/efa/lib64" +ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/lib/x86_64-linux-gnu" +ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/conda/lib/" +ENV PATH=/opt/conda/bin:/opt/aws/neuron/bin:$PATH +ENV PATH="${PATH}:/opt/amazon/efa/bin" + +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y --no-install-recommends \ + apt-transport-https \ + build-essential \ + ca-certificates \ + cmake \ + curl \ + ffmpeg \ + gcc \ + git \ + gnupg2 \ + gpg-agent \ + jq \ + libgl1 \ + libgl1-mesa-dri \ + libglib2.0-0 \ + libsm6 \ + libxext6 \ + libxrender-dev \ + libcap-dev \ + libhwloc-dev \ + openssh-client \ + openjdk-11-jdk \ + unzip \ + wget \ + zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/tmp* \ + && apt-get clean + + +# https://github.com/docker-library/openjdk/issues/261 https://github.com/docker-library/openjdk/pull/263/files +RUN keytool -importkeystore -srckeystore /etc/ssl/certs/java/cacerts -destkeystore /etc/ssl/certs/java/cacerts.jks -deststoretype JKS -srcstorepass changeit -deststorepass changeit -noprompt; \ + mv /etc/ssl/certs/java/cacerts.jks /etc/ssl/certs/java/cacerts; \ + /var/lib/dpkg/info/ca-certificates-java.postinst configure; + +RUN curl -L -o ~/miniforge.sh https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh \ + && chmod +x ~/miniforge.sh \ + && ~/miniforge.sh -b -p /opt/conda \ + && rm ~/miniforge.sh \ + && /opt/conda/bin/mamba install -c conda-forge -y \ + python=$PYTHON_VERSION \ + pyopenssl \ + cython \ + mkl-include \ + mkl \ + parso \ + # Below 2 are included in miniconda base, but not mamba so need to install + conda-content-trust \ + charset-normalizer \ + && /opt/conda/bin/conda clean -ya + +RUN /opt/conda/bin/mamba install -c conda-forge \ + python=$PYTHON_VERSION \ + scikit-learn \ + h5py \ + requests \ + && conda clean -ya \ + && pip install --upgrade pip \ + --trusted-host pypi.org --trusted-host files.pythonhosted.org \ + && ln -s /opt/conda/bin/pip /usr/local/bin/pip3 \ + && pip install \ + enum-compat \ + ipython \ + && rm -rf ~/.cache/pip/* + +# Install EFA +RUN apt-get update \ + && cd $HOME \ + && curl -O https://efa-installer.amazonaws.com/aws-efa-installer-latest.tar.gz \ + && wget https://efa-installer.amazonaws.com/aws-efa-installer.key && gpg --import aws-efa-installer.key \ + && cat aws-efa-installer.key | gpg --fingerprint \ + && wget https://efa-installer.amazonaws.com/aws-efa-installer-latest.tar.gz.sig && gpg --verify ./aws-efa-installer-latest.tar.gz.sig \ + && tar -xf aws-efa-installer-latest.tar.gz \ + && cd aws-efa-installer \ + && ./efa_installer.sh -y -g --skip-kmod --skip-limit-conf --no-verify \ + && cd $HOME \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/tmp* \ + && apt-get clean + +# Stub libcuda.so.1 so the NIXL LIBFABRIC backend can dlopen on Neuron (no CUDA driver present). +# The plugin references three CUDA *driver* entrypoints only for an optional GPUDirect path that +# is never exercised on Neuron; defining them as no-ops satisfies RTLD_NOW without a real driver. +RUN printf '%s\n' \ + 'int cuCtxSetCurrent(void* c){return 999;}' \ + 'int cuDeviceGetPCIBusId(char* s, int n, int d){return 999;}' \ + 'int cuPointerGetAttributes(void* a, void* b, unsigned long long p){return 999;}' \ + > /tmp/cuda_stub.c \ + && gcc -shared -fPIC -Wl,-soname,libcuda.so.1 -o /usr/local/lib/libcuda.so.1 /tmp/cuda_stub.c \ + && rm -f /tmp/cuda_stub.c \ + && ldconfig + +COPY --chmod=755 vllm_entrypoint.py neuron-monitor.sh deep_learning_container.py /usr/local/bin/ + +# SageMaker hosting support. SageMaker launches an inference container as +# `docker run serve`, so exposing an executable named `serve` on PATH lets the +# existing ENTRYPOINT (vllm_entrypoint.py, which execs its argv) start the vLLM server. +COPY --chmod=755 serve.sh /usr/local/bin/serve +COPY --chmod=755 sagemaker_args.py /usr/local/bin/sagemaker_args.py + +### Mount Point ### +# When launching the container, mount the code directory to /workspace +ARG APP_MOUNT=/workspace +VOLUME ${APP_MOUNT} +WORKDIR ${APP_MOUNT}/vllm + +# Install AWS CLI +RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ + && unzip awscliv2.zip \ + && ./aws/install \ + && rm -rf awscliv2.zip aws + +RUN ${PIP} install --no-cache-dir -U \ + "opencv-python" \ + "pandas" \ + "boto3" \ + "cryptography" \ + "pytest" \ + "wheel" \ + "jinja2" \ + uv \ + torchserve==${TORCHSERVE_VERSION} \ + torch-model-archiver==${TORCHSERVE_VERSION} \ + && rm -rf ~/.cache/pip/* + +RUN useradd -m model-server \ + && mkdir -p /home/model-server/tmp /opt/ml/model \ + && chown -R model-server /home/model-server /opt/ml/model +COPY config.properties /home/model-server + +# Compliance +RUN HOME_DIR=/root \ + && curl -o ${HOME_DIR}/oss_compliance.zip https://aws-dlinfra-utilities.s3.amazonaws.com/oss_compliance.zip \ + && unzip ${HOME_DIR}/oss_compliance.zip -d ${HOME_DIR}/ \ + && cp ${HOME_DIR}/oss_compliance/test/testOSSCompliance /usr/local/bin/testOSSCompliance \ + && chmod +x /usr/local/bin/testOSSCompliance \ + && chmod +x ${HOME_DIR}/oss_compliance/generate_oss_compliance.sh \ + && ${HOME_DIR}/oss_compliance/generate_oss_compliance.sh ${HOME_DIR} ${PYTHON} \ + && rm -rf ${HOME_DIR}/oss_compliance* \ + # conda leaves an empty /root/.cache/conda/notices.cache file which is not removed by conda clean -ya + && rm -rf ${HOME_DIR}/.cache/conda + +# Setting up APT and PIP repo for neuron artifacts +ARG NEURON_APT_REPO=apt.repos.neuron.amazonaws.com +ARG NEURON_PIP_REPO=pip.repos.neuron.amazonaws.com +RUN --mount=type=secret,id=neuron_repo \ + mkdir -p /etc/apt/keyrings \ + && echo "deb [signed-by=/etc/apt/keyrings/neuron.gpg] https://${NEURON_APT_REPO} jammy main" > /etc/apt/sources.list.d/neuron.list \ + && NEURON_REPO_CRED="$([ -s /run/secrets/neuron_repo ] && cat /run/secrets/neuron_repo || true)" \ + && curl $([ -n "${NEURON_REPO_CRED}" ] && echo "-u ${NEURON_REPO_CRED}") --retry 3 --retry-delay 1 --retry-all-errors -fSL "https://${NEURON_APT_REPO}/GPG-PUB-KEY-AMAZON-AWS-NEURON.PUB" | gpg --dearmor > /etc/apt/keyrings/neuron.gpg + +# Neuron SDK components version numbers +ARG NEURONX_COLLECTIVES_LIB_VERSION=2.35.43.0-354ad3064 +ARG NEURONX_RUNTIME_LIB_VERSION=2.35.30.0-d2725ccb8 +ARG NEURONX_TOOLS_VERSION=2.33.38.0-f874d5618 + +ARG NEURONX_CC_VERSION=2.28.7631.0+8f7b0cf5 +ARG NKI_VERSION=0.7.0+37713544100.gfede04bb +ARG NEURON_AGENTIC_DEVELOPMENT_VERSION=1.4 +ARG LIBTORCH_NEURONX_LITE_VERSION=2.13.0.1.0.3112+653bc48f + +# GitHub repository and branch +ARG GITHUB_REPO=https://github.com/vllm-project/vllm-neuron.git +ARG GITHUB_REPO_BRANCH=release-0.29.0.1.2.0 + +# Configure SSH access +RUN mkdir -p /root/.ssh \ + && echo "StrictHostKeyChecking no" >> /root/.ssh/config \ + && ssh-keyscan -t rsa github.com >> /root/.ssh/known_hosts + +# Clone vllm-neuron repository +RUN --mount=type=secret,id=containers_github_ssh_key,target=/root/.ssh/id_ed25519,mode=0600 \ + git clone -b ${GITHUB_REPO_BRANCH} ${GITHUB_REPO} /opt/vllm-neuron + +FROM base AS repo + + +# Install Neuron components from the apt and pip repos (latest versions) +RUN --mount=type=secret,id=neuron_repo \ + mkdir -p /etc/apt/auth.conf.d \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + printf 'machine %s login %s password %s\n' "${NEURON_APT_REPO}" "${CRED%%:*}" "${CRED#*:}" > /etc/apt/auth.conf.d/neuron.conf; \ + chmod 600 /etc/apt/auth.conf.d/neuron.conf; \ + fi \ + && apt-get update \ + && apt-get install -y \ + aws-neuronx-tools \ + aws-neuronx-collectives \ + aws-neuronx-runtime-lib \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/tmp* \ + && apt-get clean \ + && rm -f /etc/apt/auth.conf.d/neuron.conf + +RUN --mount=type=secret,id=neuron_repo \ + PIP_REPO_URL="https://${NEURON_PIP_REPO}" \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + ENC="$(printf '%s' "$CRED" | python3 -c 'import urllib.parse,sys; u,p=sys.stdin.read().split(":",1); print(urllib.parse.quote(u,safe="")+":"+urllib.parse.quote(p,safe=""))')"; \ + PIP_REPO_URL="https://${ENC}@${NEURON_PIP_REPO}"; \ + fi \ + && ${PIP} install --no-cache-dir \ + --index-url ${PIP_REPO_URL} \ + --trusted-host ${NEURON_PIP_REPO} \ + --extra-index-url ${PYPI_SIMPLE_URL} \ + neuronx-cc \ + nki \ + neuron_agentic_development \ + libtorch-neuronx-lite \ + /opt/vllm-neuron \ + && rm -rf ~/.cache/pip/* + +FROM base AS prod + +# Install Neuron components with specific versions +RUN --mount=type=secret,id=neuron_repo \ + mkdir -p /etc/apt/auth.conf.d \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + printf 'machine %s login %s password %s\n' "${NEURON_APT_REPO}" "${CRED%%:*}" "${CRED#*:}" > /etc/apt/auth.conf.d/neuron.conf; \ + chmod 600 /etc/apt/auth.conf.d/neuron.conf; \ + fi \ + && apt-get update \ + && apt-get install -y \ + aws-neuronx-tools=$NEURONX_TOOLS_VERSION \ + aws-neuronx-collectives=$NEURONX_COLLECTIVES_LIB_VERSION \ + aws-neuronx-runtime-lib=$NEURONX_RUNTIME_LIB_VERSION \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/tmp* \ + && apt-get clean \ + && rm -f /etc/apt/auth.conf.d/neuron.conf + +RUN --mount=type=secret,id=neuron_repo \ + PIP_REPO_URL="https://${NEURON_PIP_REPO}" \ + && if [ -s /run/secrets/neuron_repo ]; then \ + CRED="$(cat /run/secrets/neuron_repo)"; \ + ENC="$(printf '%s' "$CRED" | python3 -c 'import urllib.parse,sys; u,p=sys.stdin.read().split(":",1); print(urllib.parse.quote(u,safe="")+":"+urllib.parse.quote(p,safe=""))')"; \ + PIP_REPO_URL="https://${ENC}@${NEURON_PIP_REPO}"; \ + fi \ + && ${PIP} install --no-cache-dir \ + --index-url ${PIP_REPO_URL} \ + --trusted-host ${NEURON_PIP_REPO} \ + --extra-index-url ${PYPI_SIMPLE_URL} \ + neuronx-cc==$NEURONX_CC_VERSION \ + nki==$NKI_VERSION \ + neuron_agentic_development==$NEURON_AGENTIC_DEVELOPMENT_VERSION \ + libtorch-neuronx-lite==$LIBTORCH_NEURONX_LITE_VERSION \ + /opt/vllm-neuron \ + && rm -rf ~/.cache/pip/* + +FROM ${BUILD_STAGE} AS final + +# Upgrade OS packages to latest versions +RUN rm -f /etc/apt/sources.list.d/neuron.list /etc/apt/keyrings/neuron.gpg \ + && apt-get update \ + && apt-get upgrade -y \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +# Point conda at the libmamba solver, then remove the build-time rattler +# solver backend (not needed at runtime). +RUN conda config --set solver libmamba \ + && (conda remove -y --force-remove py-rattler conda-rattler-solver || true) \ + && conda clean -ya \ + && rm -rf /opt/conda/pkgs/* + +EXPOSE 8080 8081 + +ENTRYPOINT ["python", "/usr/local/bin/vllm_entrypoint.py"] +CMD ["/bin/bash"] +HEALTHCHECK CMD curl --fail http://localhost:8080/ping || exit 1