File size: 2,055 Bytes
59db361 3396ad2 59db361 3396ad2 59db361 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | # app/Dockerfile
# Build context is the je-validation project root, NOT app/ — compose sets
# `context: ..`, and the HF Space repo mirrors the same layout with this file
# copied to its root. The context's .dockerignore keeps raw snapshots out.
# Build stage: python base with uv on top; produces /app/.venv only.
FROM python:3.12-slim AS builder
COPY --from=ghcr.io/astral-sh/uv:0.5 /uv /usr/local/bin/uv
ENV UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy
WORKDIR /app
COPY app/pyproject.toml app/uv.lock ./
RUN uv sync --frozen --no-dev --no-install-project
COPY app/src ./src
RUN uv sync --frozen --no-dev
# Runtime stage: plain python, no uv. The venv is copied to the same /app path
# the builder created it at, so its interpreter links and the editable install
# stay valid.
FROM python:3.12-slim
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PATH="/app/.venv/bin:$PATH" \
JE_DATA_DIR=/data
RUN groupadd --gid 1000 appuser \
&& useradd --uid 1000 --gid 1000 --create-home appuser
WORKDIR /app
COPY --from=builder --chown=appuser:appuser /app/.venv ./.venv
COPY --chown=appuser:appuser app/src ./src
# Spec + DS-A snapshot + recorded run history baked in so the image is
# self-contained (HF Spaces has no volumes; its disk resets on restart, so
# baked runs are the only ones that survive). Local compose shadows all of
# these with its ../docs and ../data mounts. The deploy script stages a
# curated subset of data/runs/console; local builds bake whatever is there.
COPY --chown=appuser:appuser docs/spec ./docs/spec
COPY --chown=appuser:appuser data/snapshots/ds_a /data/snapshots/ds_a
COPY --chown=appuser:appuser data/runs/console /data/runs/console
RUN chown -R appuser:appuser /data
USER appuser
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/api/health', timeout=3)"
CMD ["uvicorn", "je_validation.console.api:app", \
"--host", "0.0.0.0", "--port", "8000", "--workers", "1"]
|