Tracker de vie auto-hébergé : suivi poids/calories/sport avec planning de pesées, sevrage tabac (vape) avec modèle de coût DIY et économies, et finances personnelles avec import de relevés bancaires. Architecture : FastAPI + SQLAlchemy 2.0 + PostgreSQL 16, React 18 + TS + Vite + Tailwind + ECharts, déploiement Docker Compose. Modules auto-découverts des deux côtés (pkgutil / import.meta.glob) et framework de connecteurs à deux voies (importeurs de fichiers + ingestion JSON) pour brancher de nouvelles sources sans toucher au noyau. Validé : 292 tests pytest, tsc + vite build, contrat API/web vérifié contre le schéma OpenAPI, et déploiement Docker réel sur PostgreSQL 16 (28 tables, SPA servie par nginx, wizard de premier démarrage). Documentation : README.md, docs/GUIDE.md, CONVENTIONS.md, et les documents de conception et de recherche dans docs/. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
34 lines
1.4 KiB
Docker
34 lines
1.4 KiB
Docker
# LifeTrack API — FastAPI + SQLAlchemy 2.0 on Python 3.12 (DESIGN.md, "Stack").
|
|
# Build context = repository root (docker-compose.yml).
|
|
|
|
FROM python:3.12-slim AS builder
|
|
ENV PIP_DISABLE_PIP_VERSION_CHECK=1 \
|
|
PIP_NO_CACHE_DIR=1 \
|
|
PIP_ROOT_USER_ACTION=ignore
|
|
WORKDIR /build
|
|
COPY apps/api/requirements.txt .
|
|
RUN python -m venv /opt/venv \
|
|
&& /opt/venv/bin/pip install -r requirements.txt
|
|
|
|
FROM python:3.12-slim
|
|
ENV PATH="/opt/venv/bin:$PATH" \
|
|
PYTHONUNBUFFERED=1 \
|
|
PYTHONDONTWRITEBYTECODE=1
|
|
WORKDIR /srv
|
|
COPY --from=builder /opt/venv /opt/venv
|
|
COPY apps/api/app ./app
|
|
|
|
# Non-root runtime (C7): the API never writes to disk — imports are parsed in
|
|
# memory and everything is persisted in PostgreSQL — so the whole tree can stay
|
|
# read-only for the service account.
|
|
RUN useradd --system --create-home --uid 10001 --shell /usr/sbin/nologin lifetrack \
|
|
&& chown -R lifetrack:lifetrack /srv
|
|
USER lifetrack
|
|
|
|
EXPOSE 8000
|
|
# `python` is the venv interpreter (see PATH): no curl/wget needed in the image.
|
|
# start-period covers the first boot: metadata.create_all() builds 28 tables.
|
|
HEALTHCHECK --interval=15s --timeout=5s --start-period=45s --retries=5 \
|
|
CMD ["python", "-c", "import sys, urllib.request; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8000/api/healthz', timeout=4).status == 200 else 1)"]
|
|
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|