# ========================================== # Builder Stage # ========================================== FROM python:3.13-slim AS builder # Keep runtime behavior predictable and logs visible in container environments. ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ UV_COMPILE_BYTECODE=1 WORKDIR /app # Install uv for fast dependency management COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv COPY pyproject.toml uv.lock ./ RUN --mount=type=cache,target=/root/.cache \ uv sync --locked --no-dev --no-install-project # ========================================== # Runtime Stage # ========================================== FROM python:3.13-slim AS runtime WORKDIR /app # Runtime uses a non-root user. RUN useradd --create-home --shell /usr/sbin/nologin app # Copy dependencies and application code COPY --from=builder --chown=app:app /app/.venv /app/.venv COPY --chown=app:app src ./src COPY --chown=app:app assets ./assets # Ensure runtime entrypoints stay executable RUN find /app/.venv/bin -type f -exec chmod 755 {} + USER app EXPOSE 8501 # Same endpoint as compose: verifies the server responds (slim has no curl). HEALTHCHECK --interval=30s --timeout=5s --start-period=45s --retries=3 \ CMD ["/app/.venv/bin/python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8501/_stcore/health', timeout=5).read()"] CMD ["/app/.venv/bin/python", "-m", "streamlit", "run", "src/streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0", "--server.enableXsrfProtection=false"]