diff --git a/framework/docker/base/ubi/Containerfile b/framework/docker/base/ubi/Containerfile new file mode 100644 index 000000000000..d8bd95a66afb --- /dev/null +++ b/framework/docker/base/ubi/Containerfile @@ -0,0 +1,87 @@ +# Copyright 2026 Flower Labs GmbH. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +# Multi-stage base image build +# +# Building the base image for ARM64 requires installing some additional system dependencies to +# compile the grpcio package, as they do not provide a pre-built package. However, we don't want +# the dependencies in the final base image as they are only needed to compile the package. +# That's why we're creating a multi-stage build. When installing flwr, we use a virtual +# environment to keep all files in a single isolated directory as described here: +# https://pythonspeed.com/articles/multi-stage-docker-python/ + +ARG UBI_IMAGE=registry.redhat.io/ubi9/python-312-minimal +ARG UBI_VERSION=9.7 +FROM ${UBI_IMAGE}:${UBI_VERSION} AS compile +USER 0 + +# Install system dependencies required for compiling grpcio on ARM64 +RUN microdnf install -y --nodocs \ + gcc \ + gcc-c++ \ + libffi-devel \ + && microdnf clean all \ + # create virtual env + && python -m venv /python/venv + +# Make sure we use the virtualenv +ENV PATH=/python/venv/bin:$PATH + +# Install specific version of pip, setuptools and flwr +ARG PIP_VERSION=26.0.1 +ARG SETUPTOOLS_VERSION=82.0.0 +RUN pip install -U --no-cache-dir \ + pip==${PIP_VERSION} \ + setuptools==${SETUPTOOLS_VERSION} + +ARG FLWR_VERSION=1.28.0 +ARG FLWR_PACKAGE=flwr +RUN pip install -U --no-cache-dir ${FLWR_PACKAGE}==${FLWR_VERSION} + +FROM ${UBI_IMAGE}:${UBI_VERSION} AS base +USER 0 + +# Install runtime dependencies and add non-root user +RUN microdnf install -y --nodocs \ + shadow-utils \ + && useradd \ + --no-create-home \ + --home-dir /app \ + -c "" \ + --uid 49999 app \ + && microdnf remove -y shadow-utils \ + && microdnf clean all \ + && mkdir -p /app \ + && chown -R app:app /app + +COPY --from=compile --chown=app:app /python/venv /python/venv + +# Make sure we use the virtualenv +ENV PATH=/python/venv/bin:$PATH \ + # Send stdout and stderr stream directly to the terminal. Ensures that no + # output is retained in a buffer if the application crashes. + PYTHONUNBUFFERED=1 \ + # Typically, bytecode is created on the first invocation to speed up following invocation. + # However, in Docker we only make a single invocation (when we start the container). + # Therefore, we can disable bytecode writing. + PYTHONDONTWRITEBYTECODE=1 \ + # Ensure that python encoding is always UTF-8. + PYTHONIOENCODING=UTF-8 \ + LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 + +WORKDIR /app +USER app +ENV HOME=/app