From 79953ca4364f045796b05f1b291941dbe648245c Mon Sep 17 00:00:00 2001 From: Jinyan Li Date: Thu, 6 Nov 2025 11:12:07 -0800 Subject: [PATCH 1/5] upgrade py version --- docker/1.4-2/base/Dockerfile.cpu | 110 ++---------------------------- docker/1.4-2/final/Dockerfile.cpu | 6 +- pyproject.toml | 6 +- tox.ini | 4 +- 4 files changed, 11 insertions(+), 115 deletions(-) diff --git a/docker/1.4-2/base/Dockerfile.cpu b/docker/1.4-2/base/Dockerfile.cpu index ad251c3..baa83a6 100644 --- a/docker/1.4-2/base/Dockerfile.cpu +++ b/docker/1.4-2/base/Dockerfile.cpu @@ -18,103 +18,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ apt-get clean && \ rm -rf /var/lib/apt/lists/* -# MLIO builder stage with Ubuntu 20.04 -FROM ubuntu:20.04@sha256:874aca52f79ae5f8258faff03e10ce99ae836f6e7d2df6ecd3da5c1cad3a912b as mlio-builder - -ARG PYTHON_VERSION=3.10 -ARG MLIO_VERSION=v0.9.0 -ARG PYARROW_VERSION=17.0.0 - -ENV DEBIAN_FRONTEND=noninteractive - -# Install uv and Python 3.10 -RUN apt-get update && \ - apt-get -y install --no-install-recommends \ - build-essential curl git wget ca-certificates lsb-release software-properties-common && \ - # Install uv - curl -LsSf https://astral.sh/uv/install.sh | sh && \ - mv /root/.local/bin/uv /usr/local/bin/uv && \ - # Install Python 3.10 with uv - uv python install 3.10 && \ - ln -sf $(uv python find 3.10) /usr/bin/python3.10 && \ - update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1 - - # Add Apache Arrow repository (hardcoded for Ubuntu 20.04 focal) -RUN wget https://packages.apache.org/artifactory/arrow/ubuntu/apache-arrow-apt-source-latest-focal.deb && \ - apt install -y -V ./apache-arrow-apt-source-latest-focal.deb && \ - apt-get update && \ - apt-get install -y -V libarrow-dev=17.0.0-1 libarrow-dataset-dev=17.0.0-1 libparquet-dev=17.0.0-1 libarrow-acero-dev=17.0.0-1 && \ - # MLIO build dependencies - wget http://es.archive.ubuntu.com/ubuntu/pool/main/libf/libffi/libffi7_3.3-4_amd64.deb && \ - dpkg -i libffi7_3.3-4_amd64.deb && \ - apt-get -y install --no-install-recommends \ - apt-transport-https gnupg && \ - wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | \ - gpg --dearmor - | \ - tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null && \ - echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ bionic main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null && \ - apt-get update && \ - rm /usr/share/keyrings/kitware-archive-keyring.gpg && \ - apt-get install -y --no-install-recommends \ - autoconf automake cmake cmake-data doxygen kitware-archive-keyring libcurl4-openssl-dev libssl-dev libtool ninja-build zlib1g-dev && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN ln -fs /usr/share/zoneinfo/UTC /etc/localtime && \ - dpkg-reconfigure --frontend noninteractive tzdata - -ENV PIP_ROOT_USER_ACTION=ignore - -# Build MLIO from scratch -# Clone MLIO repository -RUN cd /tmp && \ - git clone --branch ${MLIO_VERSION} https://github.com/awslabs/ml-io.git mlio - -# Patch MLIO for Arrow 17.0.0 -RUN cd /tmp/mlio && \ - sed -i 's/find_package(Arrow 14.0.1 REQUIRED/find_package(Arrow 17.0.0 REQUIRED/g' CMakeLists.txt && \ - sed -i 's/pyarrow==14.0.1/pyarrow==17.0.0/g' src/mlio-py/setup.py - -# Build MLIO third-party dependencies (includes Arrow C++) -RUN cd /tmp/mlio && \ - build-tools/build-dependency build/third-party all - -# Configure MLIO build -RUN cd /tmp/mlio && \ - mkdir -p build/release && \ - cd build/release && \ - cmake -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_PREFIX_PATH="$(pwd)/../third-party" ../.. - -# Build MLIO core -RUN cd /tmp/mlio/build/release && \ - cmake --build . && \ - cmake --build . --target install - -# Configure MLIO Python extension -RUN cd /tmp/mlio/build/release && \ - cmake -DMLIO_INCLUDE_PYTHON_EXTENSION=ON -DPYTHON_EXECUTABLE="/usr/bin/python3" \ - -DMLIO_INCLUDE_ARROW_INTEGRATION=ON -DCMAKE_PREFIX_PATH="$(pwd)/../third-party" ../.. - -# Build MLIO Python extension -RUN cd /tmp/mlio/build/release && \ - cmake --build . --target mlio-py && \ - cmake --build . --target mlio-arrow - -# Build MLIO Python wheel -RUN cd /tmp/mlio/src/mlio-py && \ - uv build - -# Copy TBB libraries and MLIO shared libraries to a location we can copy from -RUN mkdir -p /mlio-artifacts && \ - cp -r /tmp/mlio/build/third-party/lib/libtbb* /mlio-artifacts/ && \ - cp /usr/local/lib/libmlio* /mlio-artifacts/ 2>/dev/null || true && \ - cp /tmp/mlio/src/mlio-py/dist/*.whl /mlio-artifacts/ - # Main image FROM ubuntu:${UBUNTU_VERSION}@sha256:${UBUNTU_IMAGE_DIGEST} -ARG PYTHON_VERSION=3.10 -ARG PYARROW_VERSION=17.0.0 +ARG PYTHON_VERSION=3.11 ENV DEBIAN_FRONTEND=noninteractive @@ -130,12 +37,12 @@ RUN apt-get update && \ apt install -y -V ./apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb && \ apt-get update && \ apt-get install -y -V libarrow-dev=17.0.0-1 libarrow-dataset-dev=17.0.0-1 libparquet-dev=17.0.0-1 libarrow-acero-dev=17.0.0-1 && \ - # Add deadsnakes PPA for Python 3.10 + # Add deadsnakes PPA for Python 3.11 add-apt-repository ppa:deadsnakes/ppa && \ apt-get update && \ apt-get -y install --no-install-recommends \ - python3.10 python3.10-distutils python3.10-dev && \ - update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1 && \ + python3.11 python3.11-distutils python3.11-dev && \ + update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1 && \ curl -sS https://bootstrap.pypa.io/get-pip.py | python3 && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* @@ -150,15 +57,6 @@ RUN curl -LsSf https://astral.sh/uv/install.sh | sh && \ ENV PATH=/usr/local/bin:${PATH} ENV PIP_ROOT_USER_ACTION=ignore -# Copy MLIO wheel, TBB libraries, and MLIO shared libraries from builder stage -COPY --from=mlio-builder /mlio-artifacts/*.whl /tmp/ -COPY --from=mlio-builder /mlio-artifacts/libtbb* /usr/local/lib/ -COPY --from=mlio-builder /mlio-artifacts/libmlio* /usr/local/lib/ - -# Install MLIO wheel -RUN uv pip install --system /tmp/*.whl && \ - rm /tmp/*.whl - # Copy compiled SQLite from builder stage COPY --from=sqlite-builder /usr/local/bin/sqlite3 /usr/local/bin/sqlite3 COPY --from=sqlite-builder /usr/local/lib/libsqlite3.* /usr/local/lib/ diff --git a/docker/1.4-2/final/Dockerfile.cpu b/docker/1.4-2/final/Dockerfile.cpu index bd7148c..ad5f2f5 100644 --- a/docker/1.4-2/final/Dockerfile.cpu +++ b/docker/1.4-2/final/Dockerfile.cpu @@ -9,8 +9,8 @@ COPY requirements.txt /requirements.txt RUN uv pip install --system -r /requirements.txt && \ rm /requirements.txt -# Fix Python 3.10 compatibility for sagemaker-containers -RUN python3 -c "import sys; import os; site_packages = '/usr/local/lib/python3.10/dist-packages'; mapping_file = os.path.join(site_packages, 'sagemaker_containers/_mapping.py'); exec('if os.path.exists(mapping_file):\\n with open(mapping_file, \"r\") as f:\\n content = f.read()\\n content = content.replace(\"collections.Mapping\", \"collections.abc.Mapping\")\\n with open(mapping_file, \"w\") as f:\\n f.write(content)')" +# Fix Python 3.11 compatibility for sagemaker-containers +RUN python3 -c "import sys; import os; site_packages = '/usr/local/lib/python3.11/dist-packages'; mapping_file = os.path.join(site_packages, 'sagemaker_containers/_mapping.py'); exec('if os.path.exists(mapping_file):\\n with open(mapping_file, \"r\") as f:\\n content = f.read()\\n content = content.replace(\"collections.Mapping\", \"collections.abc.Mapping\")\\n with open(mapping_file, \"w\") as f:\\n f.write(content)')" COPY dist/sagemaker_sklearn_container-2.0-py3-none-any.whl /sagemaker_sklearn_container-2.0-py3-none-any.whl RUN uv pip install --system --no-cache /sagemaker_sklearn_container-2.0-py3-none-any.whl && \ @@ -56,4 +56,4 @@ EXPOSE 8080 ENV TEMP=/home/model-server/tmp # Required label for multi-model loading -LABEL com.amazonaws.sagemaker.capabilities.multi-models=true +LABEL com.amazonaws.sagemaker.capabilities.multi-models=true \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index af83527..f98581f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "sagemaker-sklearn-container" version = "2.0" description = "SageMaker Scikit-learn Container" -requires-python = "==3.10.*" +requires-python = "==3.11.*" license = "Apache-2.0" authors = [{name = "Amazon Web Services"}] classifiers = [ @@ -10,7 +10,7 @@ classifiers = [ "Intended Audience :: Developers", "Natural Language :: English", "Programming Language :: Python", - "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", ] dynamic = ["readme", "dependencies", "optional-dependencies"] @@ -31,4 +31,4 @@ where = ["src"] exclude = ["test*"] [tool.setuptools.package-dir] -"" = "src" +"" = "src" \ No newline at end of file diff --git a/tox.ini b/tox.ini index 1613ed1..9223252 100644 --- a/tox.ini +++ b/tox.ini @@ -11,13 +11,11 @@ deps = -r{toxinidir}/test-requirements.txt conda_deps= pyarrow=14.0.1 - mlio-py=0.9 conda_channels= conda-forge - mlio commands = pytest --cov=sagemaker_sklearn_container --cov-fail-under=60 test/unit [testenv:flake8] deps = flake8 -commands = flake8 setup.py src test +commands = flake8 setup.py src test \ No newline at end of file From 08f3902e1d36647aabdb2969252079c6b996873d Mon Sep 17 00:00:00 2001 From: Jinyan Li Date: Sun, 9 Nov 2025 15:11:33 -0800 Subject: [PATCH 2/5] update license format --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f98581f..4863ad5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "sagemaker-sklearn-container" version = "2.0" description = "SageMaker Scikit-learn Container" requires-python = "==3.11.*" -license = "Apache-2.0" +license = {text = "Apache-2.0"} authors = [{name = "Amazon Web Services"}] classifiers = [ "Development Status :: 5 - Production/Stable", From 0e738382fd64690cbe68858e05ea5a9608167fdb Mon Sep 17 00:00:00 2001 From: JinyanLi Date: Thu, 12 Feb 2026 07:01:52 +0000 Subject: [PATCH 3/5] Update setup.py to require Python 3.11 --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5be8842..b9db936 100644 --- a/setup.py +++ b/setup.py @@ -35,6 +35,7 @@ def read(fname): "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", ], install_requires=read("requirements.txt"), @@ -47,5 +48,5 @@ def read(fname): 'console_scripts': 'serve=sagemaker_sklearn_container.serving:serving_entrypoint' }, - python_requires='>=3.10', + python_requires='>=3.11', ) From 4cbf73a244f4aa9ce6218f39b9370e194e8aa4fa Mon Sep 17 00:00:00 2001 From: JinyanLi Date: Thu, 12 Feb 2026 19:57:19 +0000 Subject: [PATCH 4/5] rename docker dir and update dockerfiles to use new tag --- docker/{1.4-2 => 1.4-2-py311}/base/Dockerfile.cpu | 0 .../{1.4-2 => 1.4-2-py311}/extension/Dockerfile.cpu | 2 +- docker/{1.4-2 => 1.4-2-py311}/extension/README.md | 0 docker/{1.4-2 => 1.4-2-py311}/final/Dockerfile.cpu | 4 ++-- .../resources/libffi7_3.3-6_arm64.deb | Bin .../resources/mms/ExecutionParameters.java | 0 .../resources/mms/config.properties.tmp | 0 .../resources/mms/endpoints-1.0.jar | Bin 8 files changed, 3 insertions(+), 3 deletions(-) rename docker/{1.4-2 => 1.4-2-py311}/base/Dockerfile.cpu (100%) rename docker/{1.4-2 => 1.4-2-py311}/extension/Dockerfile.cpu (94%) rename docker/{1.4-2 => 1.4-2-py311}/extension/README.md (100%) rename docker/{1.4-2 => 1.4-2-py311}/final/Dockerfile.cpu (97%) rename docker/{1.4-2 => 1.4-2-py311}/resources/libffi7_3.3-6_arm64.deb (100%) rename docker/{1.4-2 => 1.4-2-py311}/resources/mms/ExecutionParameters.java (100%) rename docker/{1.4-2 => 1.4-2-py311}/resources/mms/config.properties.tmp (100%) rename docker/{1.4-2 => 1.4-2-py311}/resources/mms/endpoints-1.0.jar (100%) diff --git a/docker/1.4-2/base/Dockerfile.cpu b/docker/1.4-2-py311/base/Dockerfile.cpu similarity index 100% rename from docker/1.4-2/base/Dockerfile.cpu rename to docker/1.4-2-py311/base/Dockerfile.cpu diff --git a/docker/1.4-2/extension/Dockerfile.cpu b/docker/1.4-2-py311/extension/Dockerfile.cpu similarity index 94% rename from docker/1.4-2/extension/Dockerfile.cpu rename to docker/1.4-2-py311/extension/Dockerfile.cpu index 8550725..4ff3b08 100644 --- a/docker/1.4-2/extension/Dockerfile.cpu +++ b/docker/1.4-2-py311/extension/Dockerfile.cpu @@ -1,4 +1,4 @@ -FROM preprod-sklearn:1.4-2 +FROM preprod-sklearn:1.4-2-py311 RUN pip freeze | grep -q 'scikit-learn==1.4.2'; \ if [ $? -eq 0 ]; \ diff --git a/docker/1.4-2/extension/README.md b/docker/1.4-2-py311/extension/README.md similarity index 100% rename from docker/1.4-2/extension/README.md rename to docker/1.4-2-py311/extension/README.md diff --git a/docker/1.4-2/final/Dockerfile.cpu b/docker/1.4-2-py311/final/Dockerfile.cpu similarity index 97% rename from docker/1.4-2/final/Dockerfile.cpu rename to docker/1.4-2-py311/final/Dockerfile.cpu index ad5f2f5..ec648aa 100644 --- a/docker/1.4-2/final/Dockerfile.cpu +++ b/docker/1.4-2-py311/final/Dockerfile.cpu @@ -1,5 +1,5 @@ -FROM sklearn-base:1.4-2 -ENV SAGEMAKER_SKLEARN_VERSION 1.4-2 +FROM sklearn-base:1.4-2-py311 +ENV SAGEMAKER_SKLEARN_VERSION 1.4-2-py311 ENV PIP_ROOT_USER_ACTION=ignore LABEL com.amazonaws.sagemaker.capabilities.accept-bind-to-port=true diff --git a/docker/1.4-2/resources/libffi7_3.3-6_arm64.deb b/docker/1.4-2-py311/resources/libffi7_3.3-6_arm64.deb similarity index 100% rename from docker/1.4-2/resources/libffi7_3.3-6_arm64.deb rename to docker/1.4-2-py311/resources/libffi7_3.3-6_arm64.deb diff --git a/docker/1.4-2/resources/mms/ExecutionParameters.java b/docker/1.4-2-py311/resources/mms/ExecutionParameters.java similarity index 100% rename from docker/1.4-2/resources/mms/ExecutionParameters.java rename to docker/1.4-2-py311/resources/mms/ExecutionParameters.java diff --git a/docker/1.4-2/resources/mms/config.properties.tmp b/docker/1.4-2-py311/resources/mms/config.properties.tmp similarity index 100% rename from docker/1.4-2/resources/mms/config.properties.tmp rename to docker/1.4-2-py311/resources/mms/config.properties.tmp diff --git a/docker/1.4-2/resources/mms/endpoints-1.0.jar b/docker/1.4-2-py311/resources/mms/endpoints-1.0.jar similarity index 100% rename from docker/1.4-2/resources/mms/endpoints-1.0.jar rename to docker/1.4-2-py311/resources/mms/endpoints-1.0.jar From 572f18d4438a230fde1d74f66c8c1f9e48cc1026 Mon Sep 17 00:00:00 2001 From: JinyanLi Date: Wed, 18 Feb 2026 21:52:57 +0000 Subject: [PATCH 5/5] Upgrade scikit-learn container to Python 3.12 --- Dockerfile.test | 4 + .../base/Dockerfile.cpu | 12 +- .../extension/Dockerfile.cpu | 2 +- .../extension/README.md | 0 .../final/Dockerfile.cpu | 20 +- .../resources/libffi7_3.3-6_arm64.deb | Bin .../resources/mms/ExecutionParameters.java | 0 .../resources/mms/config.properties.tmp | 0 .../resources/mms/endpoints-1.0.jar | Bin pyproject.toml | 4 +- requirements.txt | 2 +- setup.py | 4 +- sklearn-py311-release-checklist.md | 321 ++++++++++++++++++ test_results.md | 74 ++++ 14 files changed, 425 insertions(+), 18 deletions(-) create mode 100644 Dockerfile.test rename docker/{1.4-2-py311 => 1.4-2-py312}/base/Dockerfile.cpu (92%) rename docker/{1.4-2-py311 => 1.4-2-py312}/extension/Dockerfile.cpu (94%) rename docker/{1.4-2-py311 => 1.4-2-py312}/extension/README.md (100%) rename docker/{1.4-2-py311 => 1.4-2-py312}/final/Dockerfile.cpu (72%) rename docker/{1.4-2-py311 => 1.4-2-py312}/resources/libffi7_3.3-6_arm64.deb (100%) rename docker/{1.4-2-py311 => 1.4-2-py312}/resources/mms/ExecutionParameters.java (100%) rename docker/{1.4-2-py311 => 1.4-2-py312}/resources/mms/config.properties.tmp (100%) rename docker/{1.4-2-py311 => 1.4-2-py312}/resources/mms/endpoints-1.0.jar (100%) create mode 100644 sklearn-py311-release-checklist.md create mode 100644 test_results.md diff --git a/Dockerfile.test b/Dockerfile.test new file mode 100644 index 0000000..f8c17e9 --- /dev/null +++ b/Dockerfile.test @@ -0,0 +1,4 @@ +FROM preprod-sklearn:1.4-2-py312 +ADD . /app +WORKDIR /app +RUN python3 -m pip install .[test] \ No newline at end of file diff --git a/docker/1.4-2-py311/base/Dockerfile.cpu b/docker/1.4-2-py312/base/Dockerfile.cpu similarity index 92% rename from docker/1.4-2-py311/base/Dockerfile.cpu rename to docker/1.4-2-py312/base/Dockerfile.cpu index 12ea038..7d97f5d 100644 --- a/docker/1.4-2-py311/base/Dockerfile.cpu +++ b/docker/1.4-2-py312/base/Dockerfile.cpu @@ -21,7 +21,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # Main image FROM ubuntu:${UBUNTU_VERSION}@sha256:${UBUNTU_IMAGE_DIGEST} -ARG PYTHON_VERSION=3.11 +ARG PYTHON_VERSION=3.12 ENV DEBIAN_FRONTEND=noninteractive @@ -37,15 +37,15 @@ RUN apt-get update && \ apt install -y -V ./apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb && \ apt-get update && \ apt-get install -y -V libarrow-dev=17.0.0-1 libarrow-dataset-dev=17.0.0-1 libparquet-dev=17.0.0-1 libarrow-acero-dev=17.0.0-1 && \ - # Add deadsnakes PPA for Python 3.11 + # Add deadsnakes PPA for Python 3.12 add-apt-repository ppa:deadsnakes/ppa && \ apt-get update && \ apt-get -y install --no-install-recommends \ - python3.11 python3.11-distutils python3.11-dev && \ - update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1 && \ + python3.12 python3.12-dev && \ + update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 1 && \ # Create python symlink for backward compatibility ln -sf /usr/bin/python3 /usr/bin/python && \ - curl -sS https://bootstrap.pypa.io/get-pip.py | python3 && \ + curl -sS https://bootstrap.pypa.io/get-pip.py | python3 - --break-system-packages && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* @@ -85,7 +85,7 @@ RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2 ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 PYTHONIOENCODING=UTF-8 LANG=C.UTF-8 LC_ALL=C.UTF-8 # Install core scientific packages with exact versions -RUN uv pip install --system --no-cache \ +RUN uv pip install --system --no-cache --break-system-packages \ numpy==2.1.0 \ scikit-learn==1.4.2 \ pyarrow==17.0.0 diff --git a/docker/1.4-2-py311/extension/Dockerfile.cpu b/docker/1.4-2-py312/extension/Dockerfile.cpu similarity index 94% rename from docker/1.4-2-py311/extension/Dockerfile.cpu rename to docker/1.4-2-py312/extension/Dockerfile.cpu index 4ff3b08..e9d437b 100644 --- a/docker/1.4-2-py311/extension/Dockerfile.cpu +++ b/docker/1.4-2-py312/extension/Dockerfile.cpu @@ -1,4 +1,4 @@ -FROM preprod-sklearn:1.4-2-py311 +FROM preprod-sklearn:1.4-2-py312 RUN pip freeze | grep -q 'scikit-learn==1.4.2'; \ if [ $? -eq 0 ]; \ diff --git a/docker/1.4-2-py311/extension/README.md b/docker/1.4-2-py312/extension/README.md similarity index 100% rename from docker/1.4-2-py311/extension/README.md rename to docker/1.4-2-py312/extension/README.md diff --git a/docker/1.4-2-py311/final/Dockerfile.cpu b/docker/1.4-2-py312/final/Dockerfile.cpu similarity index 72% rename from docker/1.4-2-py311/final/Dockerfile.cpu rename to docker/1.4-2-py312/final/Dockerfile.cpu index ec648aa..efe677f 100644 --- a/docker/1.4-2-py311/final/Dockerfile.cpu +++ b/docker/1.4-2-py312/final/Dockerfile.cpu @@ -1,21 +1,29 @@ -FROM sklearn-base:1.4-2-py311 -ENV SAGEMAKER_SKLEARN_VERSION 1.4-2-py311 +FROM sklearn-base:1.4-2-py312 +ENV SAGEMAKER_SKLEARN_VERSION 1.4-2-py312 ENV PIP_ROOT_USER_ACTION=ignore LABEL com.amazonaws.sagemaker.capabilities.accept-bind-to-port=true # Install remaining packages via pip COPY requirements.txt /requirements.txt -RUN uv pip install --system -r /requirements.txt && \ +RUN uv pip install --system --break-system-packages -r /requirements.txt && \ rm /requirements.txt -# Fix Python 3.11 compatibility for sagemaker-containers -RUN python3 -c "import sys; import os; site_packages = '/usr/local/lib/python3.11/dist-packages'; mapping_file = os.path.join(site_packages, 'sagemaker_containers/_mapping.py'); exec('if os.path.exists(mapping_file):\\n with open(mapping_file, \"r\") as f:\\n content = f.read()\\n content = content.replace(\"collections.Mapping\", \"collections.abc.Mapping\")\\n with open(mapping_file, \"w\") as f:\\n f.write(content)')" +# Fix Python 3.12 compatibility for sagemaker-containers +RUN python3 -c "import sys; import os; site_packages = '/usr/local/lib/python3.12/dist-packages'; mapping_file = os.path.join(site_packages, 'sagemaker_containers/_mapping.py'); exec('if os.path.exists(mapping_file):\\n with open(mapping_file, \"r\") as f:\\n content = f.read()\\n content = content.replace(\"collections.Mapping\", \"collections.abc.Mapping\")\\n with open(mapping_file, \"w\") as f:\\n f.write(content)')" COPY dist/sagemaker_sklearn_container-2.0-py3-none-any.whl /sagemaker_sklearn_container-2.0-py3-none-any.whl -RUN uv pip install --system --no-cache /sagemaker_sklearn_container-2.0-py3-none-any.whl && \ +RUN uv pip install --system --no-cache --break-system-packages /sagemaker_sklearn_container-2.0-py3-none-any.whl && \ rm /sagemaker_sklearn_container-2.0-py3-none-any.whl +# Force upgrade six to 1.16.0 after all packages are installed to ensure six.moves compatibility +RUN uv pip install --system --break-system-packages --upgrade --force-reinstall six==1.16.0 + +# Configure pip to always use --break-system-packages for Python 3.12 +RUN mkdir -p /root/.config/pip && \ + echo "[global]" > /root/.config/pip/pip.conf && \ + echo "break-system-packages = true" >> /root/.config/pip/pip.conf + ENV SAGEMAKER_TRAINING_MODULE sagemaker_sklearn_container.training:main ENV SAGEMAKER_SERVING_MODULE sagemaker_sklearn_container.serving:main diff --git a/docker/1.4-2-py311/resources/libffi7_3.3-6_arm64.deb b/docker/1.4-2-py312/resources/libffi7_3.3-6_arm64.deb similarity index 100% rename from docker/1.4-2-py311/resources/libffi7_3.3-6_arm64.deb rename to docker/1.4-2-py312/resources/libffi7_3.3-6_arm64.deb diff --git a/docker/1.4-2-py311/resources/mms/ExecutionParameters.java b/docker/1.4-2-py312/resources/mms/ExecutionParameters.java similarity index 100% rename from docker/1.4-2-py311/resources/mms/ExecutionParameters.java rename to docker/1.4-2-py312/resources/mms/ExecutionParameters.java diff --git a/docker/1.4-2-py311/resources/mms/config.properties.tmp b/docker/1.4-2-py312/resources/mms/config.properties.tmp similarity index 100% rename from docker/1.4-2-py311/resources/mms/config.properties.tmp rename to docker/1.4-2-py312/resources/mms/config.properties.tmp diff --git a/docker/1.4-2-py311/resources/mms/endpoints-1.0.jar b/docker/1.4-2-py312/resources/mms/endpoints-1.0.jar similarity index 100% rename from docker/1.4-2-py311/resources/mms/endpoints-1.0.jar rename to docker/1.4-2-py312/resources/mms/endpoints-1.0.jar diff --git a/pyproject.toml b/pyproject.toml index 4863ad5..d4ba296 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "sagemaker-sklearn-container" version = "2.0" description = "SageMaker Scikit-learn Container" -requires-python = "==3.11.*" +requires-python = "==3.12.*" license = {text = "Apache-2.0"} authors = [{name = "Amazon Web Services"}] classifiers = [ @@ -10,7 +10,7 @@ classifiers = [ "Intended Audience :: Developers", "Natural Language :: English", "Programming Language :: Python", - "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ] dynamic = ["readme", "dependencies", "optional-dependencies"] diff --git a/requirements.txt b/requirements.txt index 64d2cc3..f278f92 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,7 +24,7 @@ sagemaker-containers==2.8.6.post2 sagemaker-inference==1.2.0 sagemaker-training==4.8.0 setuptools==80.9.0 -six==1.15.0 +six==1.16.0 urllib3==1.26.17 Werkzeug==2.0.3 wheel==0.45.1 diff --git a/setup.py b/setup.py index b9db936..fb87e0e 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ def read(fname): "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ], install_requires=read("requirements.txt"), @@ -48,5 +48,5 @@ def read(fname): 'console_scripts': 'serve=sagemaker_sklearn_container.serving:serving_entrypoint' }, - python_requires='>=3.11', + python_requires='>=3.12', ) diff --git a/sklearn-py311-release-checklist.md b/sklearn-py311-release-checklist.md new file mode 100644 index 0000000..72cb4bb --- /dev/null +++ b/sklearn-py311-release-checklist.md @@ -0,0 +1,321 @@ +# Scikit-Learn 1.4-2-py311 Release Checklist + +## Overview +This is a special one-time release to upgrade Python 3.10 to Python 3.11 without MLIO support. +The new image will be tagged as `1.4-2-py311` to avoid overwriting the existing `1.4-2` (py310 with MLIO). + +## Critical Safety Measures + +### ⚠️ IMPORTANT: Pipeline Blocking Required +After updating metadata but BEFORE pushing to Alpha, you MUST block the sklearn pipeline to prevent accidental release of py310 image with py311 tags. + +--- + +## Pre-Release Checklist + +### Phase 1: Code Changes (GitHub) +- [x] Update Dockerfiles to Python 3.11 + - [x] `docker/1.4-2/base/Dockerfile.cpu` - Change `PYTHON_VERSION=3.11` + - [x] `docker/1.4-2/final/Dockerfile.cpu` - Update Python 3.11 paths and tag to `1.4-2-py311` + - [x] `docker/1.4-2/extension/Dockerfile.cpu` - Update tag to `1.4-2-py311` +- [x] Remove MLIO build from base Dockerfile +- [x] Update `pyproject.toml` - Change `requires-python = "==3.11.*"` +- [x] Update `tox.ini` - Remove mlio-py dependency +- [ ] Create GitHub PR (branch: `py311-upgrade`) +- [ ] **DO NOT MERGE YET** + +**Note:** Dockerfiles now use `1.4-2-py311` tags to match the final ECR tag that will be created. This ensures: +- Local builds: `sklearn-base:1.4-2-py311` and `preprod-sklearn:1.4-2-py311` +- CodeBuild override: `FRAMEWORK_VERSION: "1.4-2-py311"` +- Final ECR tag: `515193369038.dkr.ecr.us-west-2.amazonaws.com/sagemaker-scikit-learn:1.4-2-py311` + +### Phase 2: Local Testing (Dev Account 900597767885) +- [ ] Build images locally: + ```bash + docker build -t sklearn-base:1.4-2-py311 -f docker/1.4-2/base/Dockerfile.cpu . + python3 setup.py bdist_wheel + docker build -t preprod-sklearn:1.4-2-py311 -f docker/1.4-2/final/Dockerfile.cpu . + ``` +- [ ] Run unit tests: + ```bash + docker run --rm -t test-sklearn sh -c 'pytest --cov=sagemaker_sklearn_container --cov-fail-under=60 test/unit' + ``` +- [ ] Push to dev account with test tag: + ```bash + TEST_TAG=jinyali-py311-test + docker tag preprod-sklearn:1.4-2-py311 900597767885.dkr.ecr.us-west-2.amazonaws.com/sagemaker-scikit-learn:$TEST_TAG + docker push 900597767885.dkr.ecr.us-west-2.amazonaws.com/sagemaker-scikit-learn:$TEST_TAG + ``` +- [ ] Run integration tests (see sklearn-integ-test.md) +- [ ] Verify Python version in container: + ```bash + docker run --rm -it 900597767885.dkr.ecr.us-west-2.amazonaws.com/sagemaker-scikit-learn:$TEST_TAG python3 --version + # Should show: Python 3.11.x + ``` +- [ ] Verify MLIO is NOT installed: + ```bash + docker run --rm -it 900597767885.dkr.ecr.us-west-2.amazonaws.com/sagemaker-scikit-learn:$TEST_TAG python3 -c "import mlio" + # Should fail with ModuleNotFoundError + ``` + +--- + +## Critical Phase: Metadata & Pipeline Changes + +### Phase 3: Update Metadata Package (BEFORE CodeBuild) + +**Package**: `SMFrameworksSKLearn1_4_2IntegrationTestsMetadata` + +- [ ] Update metadata file: + ``` + File: SMFrameworksSKLearn1_4_2IntegrationTestsMetadata/src/SMFrameworksSKLearn1_4_2IntegrationTestsMetadata/src/image + + Change from: + 515193369038.dkr.ecr.us-west-2.amazonaws.com/sagemaker-scikit-learn:1.4-2 + + To: + 515193369038.dkr.ecr.us-west-2.amazonaws.com/sagemaker-scikit-learn:1.4-2-py311 + ``` +- [ ] Create CR for metadata change +- [ ] Get approval +- [ ] **MERGE metadata change** + +### Phase 4: Prepare Buildspec Override (DO NOT COMMIT) + +**Note**: Since CodeBuild webhook is broken, you'll manually override the buildspec. DO NOT commit this change. + +- [ ] Create a local copy of buildspec with py311 changes: + ```yaml + # Save as: buildspec-py311-override.yml (local file only) + + env: + variables: + FRAMEWORK_VERSION: "1.4-2-py311" # ONLY CHANGE THIS LINE + ECR_REGISTRY: "515193369038.dkr.ecr.us-west-2.amazonaws.com" + IMAGE_NAME: "sagemaker-scikit-learn" + + # Keep all other sections unchanged from original buildspec + ``` +- [ ] Save this file locally for manual CodeBuild override +- [ ] **DO NOT create CR or commit this to SMFrameworkContainersCloudFormation** + +### Phase 5: 🚨 BLOCK SKLEARN PIPELINE 🚨 + +**CRITICAL: Do this AFTER metadata merge, BEFORE pushing to Alpha** + +- [ ] Navigate to pipeline: https://pipelines.amazon.com/pipelines/SMFrameworksSKLearnECRPromoter-release +- [ ] Disable automatic triggers or add manual approval gate +- [ ] Document pipeline state before blocking +- [ ] Verify pipeline is blocked +- [ ] **Reason**: Prevent pipeline from picking up old py310 images and tagging them as py311 + +**How to block pipeline:** +- Option A: Add manual approval step before deployment stages +- Option B: Temporarily disable the pipeline +- Option C: Contact pipeline oncall for assistance + +**Pipeline Oncall**: [Add contact info or link] + +--- + +## Release Phase + +### Phase 6: Merge GitHub PR + +- [ ] Merge GitHub PR to master branch +- [ ] Verify merge successful + +### Phase 7: Trigger CodeBuild with Manual Override + +**Since CodeBuild webhook is broken, use manual override:** + +- [ ] Go to CodeBuild project in Alpha account (515193369038) +- [ ] Click "Start build with overrides" +- [ ] In build configuration: + - [ ] Set source to your GitHub PR branch (or master after merge) + - [ ] Paste your `buildspec-py311-override.yml` content into buildspec override + - [ ] Verify `FRAMEWORK_VERSION: "1.4-2-py311"` is set +- [ ] Start the build +- [ ] Monitor build progress in CodeBuild console +- [ ] Verify build succeeds + +### Phase 8: Verify Image in Alpha + +- [ ] Check Alpha ECR for new image: + ```bash + ada credentials update --once --account=515193369038 --provider=isengard --role=Admin + aws ecr describe-images --repository-name sagemaker-scikit-learn --region us-west-2 --image-ids imageTag=1.4-2-py311 + ``` +- [ ] Verify image digest is different from `1.4-2` (py310) +- [ ] Pull and test image from Alpha: + ```bash + aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin 515193369038.dkr.ecr.us-west-2.amazonaws.com + docker pull 515193369038.dkr.ecr.us-west-2.amazonaws.com/sagemaker-scikit-learn:1.4-2-py311 + docker run --rm -it 515193369038.dkr.ecr.us-west-2.amazonaws.com/sagemaker-scikit-learn:1.4-2-py311 python3 --version + ``` +- [ ] Verify Python 3.11.x +- [ ] Verify MLIO not available + +### Phase 9: 🔓 UNBLOCK SKLEARN PIPELINE + +- [ ] Verify image in Alpha is correct (py311, no MLIO) +- [ ] Re-enable pipeline triggers +- [ ] Remove manual approval gates (if added) +- [ ] Document pipeline state after unblocking + +### Phase 10: Monitor Pipeline Execution + +- [ ] Pipeline detects new image in Alpha +- [ ] Pipeline reads metadata: `1.4-2-py311` +- [ ] Verify pipeline generates correct tags: + - `1.4-2-py311-1.0.x.x` (with package version) + - `1.4-2-py311` (short tag) + - `1.4-2-py311-cpu-py3` +- [ ] Monitor pipeline stages: + - [ ] Beta deployment + - [ ] Gamma deployment + - [ ] Preprod deployment + - [ ] Prod deployment +- [ ] Check for any pipeline failures + +--- + +## Post-Release Verification + +### Phase 11: Verify Tags in Production + +Check production accounts for correct tags: + +**CMH (us-east-2)**: Account `257758044811` +```bash +aws ecr describe-images --repository-name sagemaker-scikit-learn --region us-east-2 --image-ids imageTag=1.4-2-py311 +``` + +**IAD (us-east-1)**: Account `683313688378` +```bash +aws ecr describe-images --repository-name sagemaker-scikit-learn --region us-east-1 --image-ids imageTag=1.4-2-py311 +``` + +- [ ] Verify `1.4-2-py311` exists in prod accounts +- [ ] Verify `1.4-2` (py310) still exists and unchanged +- [ ] Verify no tag collision occurred + +### Phase 12: Verify No Overlap with Existing Tags + +- [ ] Confirm existing `1.4-2` tags are untouched: + - `1.4-2` → Still points to py310 image + - `1.4-2-cpu-py3` → Still points to py310 image + - `1.4-2-1.0.56.0` → Still points to py310 image +- [ ] Confirm new `1.4-2-py311` tags exist: + - `1.4-2-py311` → Points to py311 image + - `1.4-2-py311-cpu-py3` → Points to py311 image + - `1.4-2-py311-1.0.x.x` → Points to py311 image + +### Phase 13: Integration Test in Production + +- [ ] Run a test SageMaker training job with `1.4-2-py311` +- [ ] Verify Python version in job logs +- [ ] Verify MLIO is not available +- [ ] Test inference endpoint with `1.4-2-py311` + +### Phase 14: Disable MLIO Tests + +**Package**: `SMFrameworksSKLearn1_4_2Tests` + +- [ ] Comment out or skip MLIO-related tests: + - `test_training_parquet.py` - Parquet training tests + - `test_network_isolation.py` - Network isolation with MLIO +- [ ] Create CR for test changes +- [ ] Merge test changes + +--- + +## Documentation Updates + +### Phase 15: Update Documentation + +- [ ] Update release notes mentioning py311 variant +- [ ] Document that `1.4-2-py311` does not include MLIO +- [ ] Update customer-facing docs (if needed) +- [ ] Add migration guide for customers moving from `1.4-2` to `1.4-2-py311` + +--- + +## Rollback Plan + +### If Issues Occur After Release + +**Scenario 1: Wrong tags generated** +- [ ] Stop pipeline immediately +- [ ] Revert metadata to `1.4-2` +- [ ] Delete incorrect tags from ECR +- [ ] Investigate and fix + +**Scenario 2: Pipeline released py310 with py311 tags** +- [ ] CRITICAL: Stop pipeline immediately +- [ ] Delete incorrect images from all regions +- [ ] Revert metadata changes +- [ ] Re-verify metadata before retry + +**Scenario 3: Customer impact** +- [ ] Identify affected customers +- [ ] Communicate via AWS Health Dashboard +- [ ] Provide rollback instructions +- [ ] Expedite fix + +--- + +## Key Contacts + +- **Pipeline Oncall**: [Add link] +- **SageMaker Algorithms Team**: [Add Slack channel] +- **Your Alias**: jinyali + +--- + +## Important Notes + +### Tag Comparison + +**Existing py310 tags (DO NOT TOUCH):** +- `1.4-2` +- `1.4-2-cpu-py3` +- `1.4-2-1.0.56.0` + +**New py311 tags (WILL BE CREATED):** +- `1.4-2-py311` +- `1.4-2-py311-cpu-py3` +- `1.4-2-py311-1.0.x.x` + +### Why This Approach is Safe + +1. Different tag prefix (`1.4-2-py311` vs `1.4-2`) +2. No string overlap in tag generation logic +3. Separate image digests in ECR +4. Customers must explicitly opt-in to py311 variant + +### Python 3.10 EOL Timeline + +- **Current Date**: February 2026 +- **Python 3.10 EOL**: October 2026 (~8 months) +- **Strategy**: Focus on py311, only patch py310 for critical issues + +--- + +## Completion Checklist + +- [ ] All phases completed successfully +- [ ] Both image variants coexist in production +- [ ] No customer impact reported +- [ ] Documentation updated +- [ ] Tests updated +- [ ] Pipeline unblocked and functioning normally + +--- + +## Sign-off + +- **Prepared by**: jinyali +- **Date**: [Fill in] +- **Reviewed by**: [Fill in] +- **Approved by**: [Fill in] diff --git a/test_results.md b/test_results.md new file mode 100644 index 0000000..956ce36 --- /dev/null +++ b/test_results.md @@ -0,0 +1,74 @@ +# Test Results - Python 3.12 Upgrade + +## Environment +- **Python Version**: 3.12.3 +- **Container Version**: 1.4-2-py312 +- **scikit-learn Version**: 1.4.2 +- **Test Date**: 2026-02-12 + +## Unit Tests + +### Command +```bash +docker run --rm -t test-sklearn-container sh -c 'pytest --cov=sagemaker_sklearn_container --cov-fail-under=60 test/unit' +``` + +### Results +- **Status**: ✅ PASSED +- **Tests Passed**: 43 +- **Tests Failed**: 0 +- **Warnings**: 81 +- **Test Coverage**: 68.44% (Required: 60%) +- **Execution Time**: 2.75s + +### Coverage Details +| Module | Statements | Missed | Coverage | +|--------|-----------|--------|----------| +| `__init__.py` | 0 | 0 | 100% | +| `exceptions.py` | 28 | 8 | 71% | +| `handler_service.py` | 27 | 0 | 100% | +| `mms_patch/__init__.py` | 0 | 0 | 100% | +| `mms_patch/model_server.py` | 97 | 65 | 33% | +| `serving.py` | 61 | 10 | 84% | +| `serving_mms.py` | 60 | 5 | 92% | +| `training.py` | 9 | 1 | 89% | +| **TOTAL** | **282** | **89** | **68.44%** | + +## Linting + +### Command +```bash +docker run --rm -t test-sklearn-container sh -c 'flake8 setup.py src test' +``` + +### Results +- **Status**: ✅ PASSED +- **Issues Found**: 0 + +## Python 3.12 Compatibility Notes + +### Changes Made +1. **Removed `python3.12-distutils`**: Not available in Python 3.12 (distutils removed per PEP 632) +2. **Added `--break-system-packages` flag**: Required for Python 3.12 due to PEP 668 +3. **Upgraded `six` to 1.16.0**: Fixed `six.moves` compatibility issue +4. **Updated `collections.Mapping`**: Changed to `collections.abc.Mapping` for Python 3.12 + +### Verification +```bash +# Python version +docker run --rm preprod-sklearn:1.4-2-py312 python3 --version +# Output: Python 3.12.3 + +# six version and six.moves compatibility +docker run --rm preprod-sklearn:1.4-2-py312 python3 -c "import six; print(six.__version__); from six.moves import _thread; print('six.moves works')" +# Output: 1.16.0 +# six.moves works +``` + +## Next Steps +1. ✅ Unit tests passed +2. ✅ Linting passed +3. ⏳ Push to dev account (900597767885) for integration testing +4. ⏳ Run integration tests per `sklearn-integ-test.md` +5. ⏳ Create Brazil packages for py312 variant +6. ⏳ Update pipeline configuration