v0.34.0: containerize for per-PR preview environments (flotilla SPEC §15)
This commit is contained in:
+62
@@ -0,0 +1,62 @@
|
||||
# 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"]
|
||||
Reference in New Issue
Block a user