Sync push_then_sync : préserve les absences 'publiee_escada' contre écrasement/orphelines après push (PDF Escada stale). UI reconnaît le statut (calendrier, éditeur, KPIs) au lieu d'afficher 'présent'. Sync_esacada : timeout grille 20s → 45s + retry après reload (AUTOMAT 1 échouait à la 1re classe après changement de langue). Telegram : ajoute liste d'erreurs + tail du log dans les notifs d'échec même en mode normal — avant on avait juste 'a échoué (code 1)'. UX : - Calendrier toujours visible (même sans absences) et démarre sur le mois courant (pas sur le 1er mois d'absence) ; tous les jours cliquables pour pouvoir ajouter une absence. - Date du jour pré-sélectionnée aussi via navigate_to (clic depuis /classe). - KPIs cards taggées kpi-card/kpi-value pour CSS responsive mobile. - Badge 'DEV' dans la sidebar (APP_ENV=dev) — invisible en prod. - Badge 'Built with Reflex' masqué. - KPIs retirés du dashboard /accueil. Prod : - Dockerfile.prod multi-stage (Reflex export bundle + runtime slim). - docker-compose.prod.yml séparé (port 3002, projet eptm-dashboard-prod). - .gitignore + .dockerignore nettoyés. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
78 lines
3.5 KiB
Text
78 lines
3.5 KiB
Text
# Dockerfile.prod — image immuable pour la stack prod EPTM Dashboard.
|
|
#
|
|
# Multi-stage :
|
|
# 1. builder : installe deps Python + Node, exporte le frontend Reflex.
|
|
# 2. runtime : Python slim, sans Node, sans cache npm, prêt à servir.
|
|
#
|
|
# Build : docker compose -f docker-compose.prod.yml build app
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Stage 1 — builder
|
|
FROM python:3.13 AS builder
|
|
WORKDIR /app
|
|
|
|
# Outils nécessaires au bundle frontend (Node + npm sont requis par `reflex export`).
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
curl gnupg unzip xvfb ca-certificates && \
|
|
curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
|
|
apt-get install -y nodejs && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
# Dépendances Python (installées dans le user-site pour pouvoir les copier
|
|
# proprement dans le stage 2 — évite de réinstaller pip dans le runtime).
|
|
COPY requirements.txt .
|
|
RUN pip install --no-cache-dir -r requirements.txt && \
|
|
pip install --no-cache-dir \
|
|
pdfplumber sqlalchemy plotly pandas openpyxl bcrypt pyyaml pypdf \
|
|
pyotp "qrcode[pil]" reportlab playwright markdown
|
|
|
|
# Playwright : navigateur installé en system-wide pour le stage 2.
|
|
RUN playwright install --with-deps chromium
|
|
|
|
# Code applicatif + assets statiques + docs + templates AcroForm.
|
|
COPY . .
|
|
|
|
# `reflex init` prépare la conf locale (.web/, alembic, etc.).
|
|
# `reflex export --frontend-only --no-zip` génère le bundle Vite statique
|
|
# dans .web/build/ — c'est ce que servira le backend en prod.
|
|
RUN reflex init && \
|
|
reflex export --frontend-only --no-zip
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Stage 2 — runtime
|
|
FROM python:3.13
|
|
WORKDIR /app
|
|
|
|
# Runtime allégé : Node n'est PAS réinstallé (`reflex export` a déjà créé le
|
|
# bundle). On garde curl pour les healthchecks et ca-certificates pour SMTP/HTTPS.
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
curl ca-certificates tzdata && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
# Copie les Python deps installées dans le builder.
|
|
COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
|
|
COPY --from=builder /usr/local/bin /usr/local/bin
|
|
|
|
# Playwright browsers (cache global déjà téléchargé dans le builder).
|
|
COPY --from=builder /root/.cache/ms-playwright /root/.cache/ms-playwright
|
|
|
|
# Libs système requises par Chromium headless (libnspr4, libnss3, fonts, etc.).
|
|
# Sans ça, le binaire chromium-headless-shell ne charge pas et la sync Escada
|
|
# meurt avec "error while loading shared libraries: libnspr4.so".
|
|
RUN apt-get update && \
|
|
playwright install-deps chromium && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
# Copie l'app entièrement déjà bundlée (avec .web/ + reflex.json + etc.).
|
|
COPY --from=builder /app /app
|
|
|
|
# Reflex 0.9+ exige un seul port en prod (frontend statique + backend granian).
|
|
# 3002 choisi pour cohabiter avec dev (3001 frontend Vite + 8001 backend).
|
|
ENV FRONTEND_PORT=3002 BACKEND_PORT=3002 \
|
|
TZ=Europe/Zurich \
|
|
PYTHONUNBUFFERED=1
|
|
|
|
EXPOSE 3002
|
|
|
|
# `reflex run --env prod` lance backend granian + sert le frontend depuis .web/build.
|
|
CMD ["reflex", "run", "--env", "prod"]
|