Publish curated ITWorx-ModelForge source from 990401737f96c8d46a9f7b0d84994516cadcb6a0
This commit is contained in:
1 parent
7082ab955a
commit
848f0d8f8a
434 files changed
+67298
-4315
No files matched your search
+56
-21
@@ -1,27 +1,59 @@
|
||||
FROM python:3.12-slim-trixie@sha256:09f7da3bc104798d0afb40bc08d23ab2da20a76130cec1f2ef170848f5d85217 AS builder
|
||||
# Canonical's maintained glibc-compatible Python runtime is kept as a named stage so the builder
|
||||
# can preserve its passwd/group contract without adding a shell or package manager to the final
|
||||
# image.
|
||||
FROM ubuntu/python:3.12-24.04@sha256:d5b4c1e1da458c6e10da9d7f42276d8d640ed5a0d87b1cced734a9434c531a62 AS runtime-base
|
||||
|
||||
# The builder is deliberately separate from the runtime. The agent only needs the Python
|
||||
# application packages at runtime; a full Debian build environment must not become part of the
|
||||
# shipped image or its vulnerability surface.
|
||||
FROM python:3.12-slim-trixie@sha256:e5c9fa26ffb76e11e0f054f30dc2523a2f9693f0c36c0cf1e39b27e152d899fc AS builder
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1
|
||||
|
||||
WORKDIR /build
|
||||
COPY config/security/build-toolchain.lock /tmp/modelforge-build-toolchain.lock
|
||||
COPY backend ./backend
|
||||
COPY node-agent ./node-agent
|
||||
RUN python -m venv /opt/venv \
|
||||
&& /opt/venv/bin/pip install --no-cache-dir --upgrade pip "setuptools>=78.1.1" "msgpack>=1.2.1" \
|
||||
&& /opt/venv/bin/pip install --no-cache-dir ./backend ./node-agent \
|
||||
&& /opt/venv/bin/pip check \
|
||||
&& /opt/venv/bin/python -m pip uninstall --yes pip setuptools
|
||||
|
||||
FROM python:3.12-slim-trixie@sha256:09f7da3bc104798d0afb40bc08d23ab2da20a76130cec1f2ef170848f5d85217
|
||||
# Install into a plain target directory so the final image can use Canonical's maintained,
|
||||
# glibc-compatible chiselled Python runtime. Hash-locked build tooling is removed inside the
|
||||
# builder only; no installer or build-backend metadata is carried into the runtime image. The
|
||||
# target install ignores the builder venv so a build-only package cannot mask a runtime dependency.
|
||||
# The import check exercises the same dependency closure that the final image receives without
|
||||
# contacting the control plane or touching a model repository.
|
||||
RUN python -m venv /opt/build-venv \
|
||||
&& /opt/build-venv/bin/python -m pip install --no-cache-dir --disable-pip-version-check \
|
||||
--require-hashes --only-binary=:all: --index-url https://pypi.org/simple \
|
||||
-r /tmp/modelforge-build-toolchain.lock \
|
||||
&& /opt/build-venv/bin/python -m pip install --no-cache-dir --disable-pip-version-check \
|
||||
--no-build-isolation --ignore-installed --no-compile \
|
||||
--target /opt/site-packages ./backend ./node-agent \
|
||||
&& PYTHONPATH=/opt/site-packages /opt/build-venv/bin/python -m pip check \
|
||||
&& PYTHONPATH=/opt/site-packages /opt/build-venv/bin/python -c \
|
||||
"import httpx, psutil, pynvml, modelforge_api, modelforge_node_agent" \
|
||||
&& /opt/build-venv/bin/python -m pip uninstall --yes pip setuptools wheel editables hatchling pathspec \
|
||||
pluggy tomlkit trove-classifiers
|
||||
|
||||
# Prepare the fixed runtime contract without requiring a shell or package manager in the final
|
||||
# image. The numeric IDs are intentional: Compose and existing volumes rely on UID 100/GID 101.
|
||||
RUN mkdir -p /runtime/app /runtime/data/state /runtime/data/hf-cache \
|
||||
/runtime/data/artifacts /runtime/data/quarantine \
|
||||
&& chown -R 100:101 /runtime/app /runtime/data
|
||||
|
||||
# Preserve the canonical runtime's passwd/group entries and add the existing ModelForge identity
|
||||
# with its established home directory. The final image remains shell-less and runs numerically as
|
||||
# UID 100/GID 101, while libraries that resolve the process user still see the same contract.
|
||||
COPY --from=runtime-base /etc/passwd /runtime/etc/passwd
|
||||
COPY --from=runtime-base /etc/group /runtime/etc/group
|
||||
RUN python -c "from pathlib import Path; p=Path('/runtime/etc/passwd'); s=p.read_text(); p.write_text(s if '\\nmodelforge-agent:' in s else s.rstrip('\\n')+'\\nmodelforge-agent:x:100:101::/app:/usr/sbin/nologin\\n'); p=Path('/runtime/etc/group'); s=p.read_text(); p.write_text(s if '\\nmodelforge-agent:' in s else s.rstrip('\\n')+'\\nmodelforge-agent:x:101:\\n')"
|
||||
|
||||
FROM runtime-base
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
PATH="/opt/venv/bin:${PATH}"
|
||||
|
||||
RUN apt-get update \
|
||||
&& DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& /usr/local/bin/python -m pip uninstall --yes pip setuptools
|
||||
PYTHONPATH=/opt/site-packages \
|
||||
HOME=/app
|
||||
|
||||
# Build identity. These are stamped in at build time so a running container can say exactly
|
||||
# where it came from; an argument that is never passed stays empty and is reported as null
|
||||
@@ -36,17 +68,20 @@ LABEL org.opencontainers.image.description="Outbound-only compute node agent for
|
||||
LABEL org.opencontainers.image.version="${MODELFORGE_VERSION}"
|
||||
LABEL org.opencontainers.image.revision="${MODELFORGE_COMMIT}"
|
||||
LABEL org.opencontainers.image.created="${MODELFORGE_BUILT_AT}"
|
||||
LABEL org.opencontainers.image.source="https://git.example.com/example/modelforge.git"
|
||||
LABEL org.opencontainers.image.source="https://git.example.com/example/modelforge"
|
||||
LABEL org.opencontainers.image.vendor="ITWorx"
|
||||
LABEL org.opencontainers.image.licenses="AGPL-3.0-or-later"
|
||||
|
||||
COPY --from=builder /opt/venv /opt/venv
|
||||
COPY --from=builder --chown=100:101 /opt/site-packages /opt/site-packages
|
||||
COPY --from=builder --chown=100:101 /runtime/app /app
|
||||
COPY --from=builder --chown=100:101 /runtime/data /data
|
||||
COPY --from=builder /runtime/etc/passwd /etc/passwd
|
||||
COPY --from=builder /runtime/etc/group /etc/group
|
||||
|
||||
RUN groupadd --system --gid 101 modelforge-agent \
|
||||
&& useradd --system --uid 100 --gid 101 --home-dir /app --create-home modelforge-agent \
|
||||
&& mkdir -p /data/state /data/hf-cache /data/artifacts /data/quarantine \
|
||||
&& chown -R modelforge-agent:modelforge-agent /data
|
||||
WORKDIR /app
|
||||
USER modelforge-agent
|
||||
USER 100:101
|
||||
|
||||
CMD ["modelforge-node-agent"]
|
||||
# Canonical's rock image has a Pebble entrypoint. The agent has no init supervisor requirement,
|
||||
# so explicitly remove it and invoke the reviewed Python module directly.
|
||||
ENTRYPOINT []
|
||||
CMD ["python3", "-m", "modelforge_node_agent.main"]
|
||||
Reference in new issue
Block a user