# Stage 1: Build dependencies FROM docker.io/python:3.13-alpine3.22 AS deps COPY --from=ghcr.io/astral-sh/uv:0.10.4 /uv /uvx /bin/ WORKDIR /app ENV UV_COMPILE_BYTECODE=1 \ UV_PROJECT_ENVIRONMENT=/opt/venv COPY pyproject.toml uv.lock ./ RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --frozen --no-install-project --no-dev --no-editable # Stage 2: Build backend source FROM deps AS backend-builder COPY . . # Stage 3: Build staticfiles FROM deps AS static-builder COPY . . RUN uv run --no-dev python manage.py collectstatic --noinput # Stage 3: Runtime application image FROM docker.io/python:3.13-alpine3.22 AS app WORKDIR /app COPY --from=deps /opt/venv /opt/venv COPY --from=backend-builder /app /app RUN chmod +x scripts/entrypoint.sh && \ adduser -D -g '' app && \ chown -R app:app /app ENV PATH="/opt/venv/bin:$PATH" \ PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PYTHONOPTIMIZE=2 \ DJANGO_SETTINGS_MODULE=config.settings USER app EXPOSE 8080 HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --start-interval=2s --retries=3 \ CMD wget -qO- http://127.0.0.1:8080/health || exit 1 ENTRYPOINT ["scripts/entrypoint.sh"] # Stage 4: Staticfiles image FROM docker.io/nginx:1.29-alpine-slim AS staticfiles COPY --from=static-builder /app/static /usr/share/nginx/html CMD ["nginx", "-g", "daemon off;"]