-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathDockerfile.prod
More file actions
87 lines (68 loc) · 2.89 KB
/
Copy pathDockerfile.prod
File metadata and controls
87 lines (68 loc) · 2.89 KB
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# syntax=docker/dockerfile:1
#
# Production image for Kindred. Single combined artifact: FastAPI backend
# serves the built React SPA from /app/static/. Used by web + worker modes
# (worker overrides CMD to run arq). Built and pushed by .github/workflows/
# release.yml on every v*.*.* tag.
# ---- Stage 1: build the frontend with pnpm ---------------------------------
FROM --platform=$BUILDPLATFORM node:22-slim AS frontend-builder
WORKDIR /build
# Install pnpm directly
RUN npm install -g pnpm@11.3.0
# pnpm workspace files first for layer caching
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY frontend/package.json frontend/
# Vite build doesn't need Playwright's bundled browsers / ffmpeg (~400 MB).
ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
RUN pnpm install --frozen-lockfile
# Source + build
COPY frontend/ frontend/
# Vite build args. Default to empty string for same-origin relative API calls.
ARG VITE_API_URL=""
ARG VITE_AUTH_MODE=local
ARG VITE_CF_LOGOUT_URL=
ARG APP_VERSION=
ARG GIT_HASH=
ENV VITE_API_URL=${VITE_API_URL} \
VITE_AUTH_MODE=${VITE_AUTH_MODE} \
VITE_CF_LOGOUT_URL=${VITE_CF_LOGOUT_URL} \
APP_VERSION=${APP_VERSION} \
GIT_HASH=${GIT_HASH} \
NODE_ENV=production
RUN pnpm --filter frontend build
# produces /build/frontend/dist
# ---- Stage 2: python runtime -----------------------------------------------
FROM python:3.14-slim AS runtime
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
UV_LINK_MODE=copy \
UV_COMPILE_BYTECODE=0 \
PATH="/app/.venv/bin:$PATH" \
STATIC_DIR=/app/static
# System deps: libpq for psycopg, curl for healthchecks, build-essential for
# any sdist that needs compiling. Cleaned up to keep the image lean.
RUN apt-get update && \
apt-get install -y --no-install-recommends \
build-essential libpq-dev curl ca-certificates && \
rm -rf /var/lib/apt/lists/*
# Install uv from PyPI
RUN pip install --no-cache-dir uv==0.9.26
WORKDIR /app
# Workspace metadata first (cached by uv layer)
COPY pyproject.toml uv.lock ./
# Install only the `app` workspace member (skips dev deps)
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-install-workspace --package app --no-dev
# Copy backend source after deps so code edits don't bust the dep cache
COPY backend/scripts /app/backend/scripts
COPY backend/pyproject.toml backend/alembic.ini /app/backend/
COPY backend/app /app/backend/app
# Materialize the workspace member install
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --package app --no-dev
# Built SPA → /app/static (served by FastAPI's StaticFiles when STATIC_DIR is set)
COPY --from=frontend-builder /build/frontend/dist /app/static
WORKDIR /app/backend
EXPOSE 8000
# Default to web mode. compose.yml's worker service overrides this with arq.
CMD ["bash", "-c", "bash scripts/prestart.sh && fastapi run --workers ${WEB_CONCURRENCY:-2} app/main.py --host 0.0.0.0 --port 8000"]