wedge(002/T103): web Dockerfile + M2MW_STATIC_DIR (site-packages path fix); merge T101/T102

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
m2 (AI Agent) 2026-07-02 05:49:09 +02:00
parent 61dee644d7
commit 0aeacfd14f
3 changed files with 34 additions and 2 deletions

View file

@ -1 +1 @@
{"feature_directory":"specs/001-market-first-wedge"}
{"feature_directory":"specs/002-market-web"}

24
web/Dockerfile Normal file
View file

@ -0,0 +1,24 @@
# m2-market-web — FastAPI proxy + React SPA in one container (specs/002-market-web).
# Build context: repo root (needs web/backend + web/frontend).
FROM node:20-slim AS frontend
WORKDIR /fe
COPY web/frontend/package.json web/frontend/package-lock.json* ./
RUN npm install --no-audit --no-fund
COPY web/frontend/ ./
RUN npm run build
FROM python:3.12-slim
WORKDIR /app
COPY web/backend/pyproject.toml ./backend/pyproject.toml
COPY web/backend/src ./backend/src
RUN pip install --no-cache-dir ./backend
COPY --from=frontend /fe/dist ./frontend/dist
ENV M2MW_STATIC_DIR=/app/frontend/dist
RUN groupadd --system web && useradd --system --gid web web
USER web
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=2)" || exit 1
CMD ["uvicorn", "m2_market_web.main:app", "--host", "0.0.0.0", "--port", "8000"]

View file

@ -1,5 +1,6 @@
from __future__ import annotations
import os
from pathlib import Path
from fastapi import FastAPI, Request
@ -19,7 +20,14 @@ def create_app() -> FastAPI:
def health() -> dict[str, str]:
return {"status": "healthy"}
dist = Path(__file__).resolve().parents[3] / "frontend" / "dist"
# In the container the package is pip-installed (site-packages), so the
# repo-relative parents[3] fallback misses — M2MW_STATIC_DIR wins.
dist = Path(
os.environ.get(
"M2MW_STATIC_DIR",
Path(__file__).resolve().parents[3] / "frontend" / "dist",
)
)
@app.get("/{path:path}", include_in_schema=False)
def static_or_spa(path: str, request: Request):