63 lines
2.7 KiB
Docker
63 lines
2.7 KiB
Docker
# rfc-app container image — the Cloud Run keystone for per-PR preview
|
|
# environments (flotilla SPEC §15). NOT used by production: prod still deploys
|
|
# via the pin-based on-VM gesture (flotilla §8). This image exists so flotilla
|
|
# `preview up --pr=N` can build a PR's tree and run it as an ephemeral,
|
|
# scale-to-zero Cloud Run service with a SEEDED SYNTHETIC database and ZERO real
|
|
# secrets (test-secret env only — flotilla §15 / §3 invariant 1).
|
|
#
|
|
# Single container, single port: nginx serves the built SPA on $PORT (Cloud Run
|
|
# injects it) and reverse-proxies /api/ + /auth/ to a single-process uvicorn on
|
|
# 127.0.0.1:8000 — mirroring the prod nginx + systemd split
|
|
# (deploy/nginx/ohm.wiggleverse.org.conf, deploy/systemd/rfc-app.service), so a
|
|
# preview behaves like prod minus the secrets. Single uvicorn process + single
|
|
# SQLite file, per §4.2 (never scale workers).
|
|
#
|
|
# Build context is the repo root: docker build -t <image> .
|
|
|
|
# ---- stage 1: build the Vite SPA -------------------------------------------
|
|
FROM node:20-slim AS web
|
|
WORKDIR /app/frontend
|
|
COPY frontend/package.json frontend/package-lock.json ./
|
|
RUN npm ci
|
|
COPY frontend/ ./
|
|
# VITE_* values are baked into the bundle at build time (intentionally public —
|
|
# §8 phase-5 note). VITE_APP_NAME is REQUIRED by vite.config.js (the framework
|
|
# ships no default — each deployment names itself); previews self-name. Turnstile
|
|
# uses Cloudflare's always-pass test SITE key so the widget renders + auto-passes.
|
|
ARG VITE_APP_NAME="RFC App (preview)"
|
|
ARG VITE_TURNSTILE_SITE_KEY=1x00000000000000000000AA
|
|
ARG VITE_AMPLITUDE_API_KEY=
|
|
RUN VITE_APP_NAME="$VITE_APP_NAME" \
|
|
VITE_TURNSTILE_SITE_KEY="$VITE_TURNSTILE_SITE_KEY" \
|
|
VITE_AMPLITUDE_API_KEY="$VITE_AMPLITUDE_API_KEY" \
|
|
npm run build
|
|
|
|
# ---- stage 2: runtime (backend + nginx) ------------------------------------
|
|
FROM python:3.12-slim AS runtime
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends nginx gettext-base sqlite3 \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
WORKDIR /opt/rfc-app
|
|
|
|
# Backend deps first for layer caching.
|
|
COPY backend/requirements.txt backend/requirements.txt
|
|
RUN pip install --no-cache-dir -r backend/requirements.txt
|
|
|
|
COPY backend/ backend/
|
|
COPY deploy/preview/ deploy/preview/
|
|
# health.py reads VERSION at parents[2] (== /opt/rfc-app/VERSION).
|
|
COPY VERSION ./
|
|
COPY --from=web /app/frontend/dist/ frontend/dist/
|
|
|
|
RUN chmod +x deploy/preview/entrypoint.sh
|
|
|
|
# Cloud Run injects $PORT (default 8080); the entrypoint renders nginx against
|
|
# it. The synthetic preview DB lives on the container's ephemeral filesystem and
|
|
# dies with the instance (zero create/seed/drop lifecycle — §15).
|
|
ENV PORT=8080 \
|
|
DATABASE_PATH=/opt/rfc-app/backend/data/rfc-app.db
|
|
EXPOSE 8080
|
|
|
|
ENTRYPOINT ["deploy/preview/entrypoint.sh"]
|