# Base images are pinned to an immutable digest (in addition to a human-readable # tag) so every build resolves the exact same layers (#563). # Node.js is sourced from the official, digest-pinned image rather than piping a # remote setup script into bash (`curl ... | bash -`), which performed no # checksum or signature verification of the downloaded installer (#566). The # image digest is the integrity check, and the copy is architecture-agnostic. FROM node:22.23.0-slim@sha256:d9f850096136edbc402debdd8729579a288aac64574ada0ff4db26b6ae58b0b2 AS node FROM python:3.12.13-slim-bookworm@sha256:76d4b7b6305788c6b4c6a19d6a22a3921bf802e9af4d5e1e5bd771208dba74bf AS builder RUN apt-get update && \ apt-get install -y --no-install-recommends build-essential ca-certificates curl && \ rm -rf /var/lib/apt/lists/* ENV PATH="/root/.cargo/bin:${PATH}" RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \ sh -s -- -y --profile minimal --default-toolchain none && \ rustup toolchain install 1.88 --profile minimal && \ rustup default 1.88 WORKDIR /app # Install dependencies from the committed lockfile (#567): `uv export --frozen` # reads uv.lock as-is and emits a pinned, hash-verified set installed with # --no-deps (no re-resolution). Copied first so this layer caches independently # of application source. COPY pyproject.toml uv.lock README.md ./ RUN pip install --no-cache-dir uv && \ uv export --frozen --no-dev --extra server --no-emit-project > requirements.txt && \ uv pip install --system --no-deps -r requirements.txt && \ uv pip install --system --no-deps "maturin>=1.12.6,<2" COPY . . # Install the project itself without re-resolving dependencies. RUN uv pip install --system --no-deps . && \ maturin build --release \ --manifest-path rust/crates/openjarvis-python/Cargo.toml \ --interpreter python3 \ --out /tmp/openjarvis-rust-wheel && \ uv pip install --system --no-deps /tmp/openjarvis-rust-wheel/*.whl && \ python3 -c "import openjarvis_rust; print('openjarvis_rust ok')" && \ python3 -m pip uninstall -y maturin && \ rm -rf /tmp/openjarvis-rust-wheel rust/target FROM python:3.12.13-slim-bookworm@sha256:76d4b7b6305788c6b4c6a19d6a22a3921bf802e9af4d5e1e5bd771208dba74bf # libstdc++6 + ca-certificates are the only runtime requirements of the Node # binary copied below (the python slim image already provides libc/libgcc). RUN apt-get update && \ apt-get install -y --no-install-recommends ca-certificates libstdc++6 && \ rm -rf /var/lib/apt/lists/* COPY --from=builder /usr/local /usr/local COPY --from=builder /app /app # Transplant the Node.js runtime from the official image. Both images are Debian # bookworm, so the glibc/libstdc++ ABI matches. COPY --from=node /usr/local/bin/node /usr/local/bin/node COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules RUN ln -sf /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \ ln -sf /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx WORKDIR /app LABEL openjarvis-sandbox=true ENTRYPOINT ["python", "-m", "openjarvis.sandbox.entrypoint"]