feat(pewpewstudio): laser job studio on nh3-docker :8185 (api + Caddy front), Homepage tile

Prime's directive via pewpew-dev. Images are built on nh3-dev from a clean
archive of vh/pewpewstudio (26bba3c; hamr over gitea SSH via BuildKit --ssh)
and loaded on nh3-docker. Caddy serves the SPA and strips /api/ in front of
the backend. It refuses foreign Host headers inside a route block, because the
Host rewrite would otherwise bypass the backend's TrustedHost. The DB, assets
and the app-edited shop config live on named volumes inside nh3-docker's
nightly vzdump. Verified: SPA, /api/machines and /api/generate/workflows 200;
foreign Host 400.
This commit is contained in:
vh
2026-10-13 21:39:44 -07:00
parent 5e8307ed7a
commit d1192ca868
5 changed files with 160 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
# syntax=docker/dockerfile:1.7
# pewpewstudio images, built on nh3-dev from a clean `git archive` of vh/pewpewstudio (see ../README.md).
# api: the FastAPI backend (core.api), venv built with uv; hamr is a git dependency over gitea SSH (BuildKit --ssh).
# web: Caddy serving the SPA (web/dist) and proxying /api/* to the api with the prefix stripped (Caddyfile mounted).
FROM python:3.12-slim-bookworm AS build
RUN apt-get update && apt-get install -y --no-install-recommends git openssh-client build-essential \
&& rm -rf /var/lib/apt/lists/* && pip install --no-cache-dir uv==0.13.0
# gitea's SSH is 10.250.50.70:222; the lockfile names ssh://git@gitea.phasefinal.com/vh/hamr.git, as nh3-dev's ssh config maps it
RUN install -d -m 700 /root/.ssh \
&& printf 'Host gitea.phasefinal.com\n HostName 10.250.50.70\n Port 222\n User git\n' > /root/.ssh/config \
&& ssh-keyscan -p 222 10.250.50.70 > /root/.ssh/known_hosts 2>/dev/null
ENV UV_LINK_MODE=copy UV_PYTHON_DOWNLOADS=never UV_PROJECT_ENVIRONMENT=/app/.venv
WORKDIR /app
COPY . /app
RUN --mount=type=ssh uv sync --frozen --no-dev && uv --version > /app/.uv-version
FROM python:3.12-slim-bookworm AS api
COPY --from=build /app /app
RUN install -d -o 1000 -g 1000 /state /state/assets /config
WORKDIR /app
ENV PATH=/app/.venv/bin:$PATH PYTHONUNBUFFERED=1
USER 1000:1000
EXPOSE 8000
CMD ["python", "-c", "import uvicorn; from core.api.app import create_app; from core.api.config import ApiConfig; uvicorn.run(create_app(ApiConfig.from_env()), host='0.0.0.0', port=8000)"]
FROM oven/bun:1.3 AS webbuild
WORKDIR /web
COPY web/ /web/
RUN bun install --frozen-lockfile && bun run build
FROM caddy:2-alpine AS web
COPY --from=webbuild /web/dist /srv