# syntax=docker/dockerfile:1 # Native standalone build for pyfconfig. # # Produces a single self-contained executable bundling the app, its # dependencies, the Python standard library and the GraalPy runtime, using # GraalPy's `standalone native` command (backed by GraalVM Native Image). # # Unlike Dockerfile.graalpy, the executable does not run granian/rloop: those # are native extensions that cannot be bundled into a standalone binary and # granian spawns workers through multiprocessing. The app is served over ASGI # by Hypercorn (pure Python) instead; see native/entrypoint.py. # # Build requirements: network access to the Gitea registry, PyPI, Maven Central # and the base images, plus enough RAM for native-image (see NATIVE_IMAGE_XMX). ARG GRAALPY_IMAGE=ghcr.io/graalvm/graalpy-community:25 ARG NATIVE_IMAGE_TOOLS=ghcr.io/graalvm/native-image-community:25 # GraalVM CE with native-image and javac, version-matched to the GraalPy # distribution below. Copied into the builder so the standalone build does not # download a JDK at build time. FROM ${NATIVE_IMAGE_TOOLS} AS tools # --- Builder --------------------------------------------------------------- FROM ${GRAALPY_IMAGE} AS builder ARG NATIVE_IMAGE_XMX=5500m COPY --from=tools /usr/lib64/graalvm/graalvm-community-java25 /usr/lib64/graalvm/graalvm-community-java25 ENV JAVA_HOME=/usr/lib64/graalvm/graalvm-community-java25 \ PATH=/usr/lib64/graalvm/graalvm-community-java25/bin:${PATH} # native-image links the executable against zlib; the runtime library is # present but the linker needs the -devel package (libz.so). RUN dnf install -y zlib-devel \ && dnf clean all WORKDIR /build COPY pyproject.toml README.md requirements-native.txt ./ COPY src/ ./src/ COPY native/ ./native/ RUN graalpy -m venv /opt/venv \ && /opt/venv/bin/pip install \ --index-url https://gitea.woggioni.net/api/packages/woggioni/pypi/simple \ --extra-index-url https://pypi.org/simple \ -r requirements-native.txt \ && /opt/venv/bin/pip install --no-deps . # -Os builds an interpreter-only Truffle runtime: much lower build memory and a # smaller binary, at the cost of peak throughput. Remove it to enable the JIT. # The cache mount keeps the Maven artifacts across builds. RUN --mount=type=cache,target=/opt/graalpy-25.0.2/downloaded_standalone_resources \ mkdir -p /out \ && graalpy -m standalone native \ -m native/entrypoint.py \ --venv /opt/venv \ -o /out/pyfconfig \ -ce -Os \ -N-J-Xmx${NATIVE_IMAGE_XMX} -N-J-Xms512m # --- Runtime --------------------------------------------------------------- FROM oraclelinux:10-slim RUN useradd -r -s /sbin/nologin -d /home/app -m app COPY --from=builder /out/pyfconfig /usr/local/bin/pyfconfig ENV HOME=/home/app \ HOST=0.0.0.0 \ PORT=8080 USER app EXPOSE 8080 HEALTHCHECK --interval=30s --timeout=3s --start-period=10s \ CMD curl -fsS "http://127.0.0.1:${PORT}/api/health" || exit 1 CMD ["/usr/local/bin/pyfconfig"]