feat: déploiement Docker en conteneur unique (API + UI)
Le backend FastAPI sert déjà le SPA buildé : on abandonne le duo nginx + backend au profit d'une seule image multi-stage (build Vue puis service par le backend). docker-compose passe à un service unique, avec PLESNA_DATA_DIR déclarant le stockage persistant. - backend.Dockerfile : stage node build -> copie frontend/dist, CMD en `uv run --no-sync` (plus de resync des deps dev au démarrage) - docker-compose.yml : service unique `app`, volume ./data, PLESNA_DATA_DIR=/app/data - supprime frontend/Dockerfile, frontend/nginx.conf, frontend/.dockerignore - .dockerignore : ignore **/node_modules, data, data_bck - README : section Production mise à jour Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -3,9 +3,14 @@
|
|||||||
venv
|
venv
|
||||||
__pycache__
|
__pycache__
|
||||||
*.pyc
|
*.pyc
|
||||||
|
# node_modules réinstallés dans le stage de build (à tous les niveaux)
|
||||||
node_modules
|
node_modules
|
||||||
|
**/node_modules
|
||||||
|
# frontend/dist est rebuildé dans l'image, jamais copié depuis l'hôte
|
||||||
frontend/dist
|
frontend/dist
|
||||||
|
# données locales : ne jamais les embarquer dans l'image
|
||||||
data
|
data
|
||||||
|
data_bck
|
||||||
*.egg-info
|
*.egg-info
|
||||||
.mypy_cache
|
.mypy_cache
|
||||||
.ruff_cache
|
.ruff_cache
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -37,12 +37,20 @@ Ouvrir **http://localhost:5173** — le proxy Vite redirige `/api` vers le backe
|
|||||||
|
|
||||||
## Production (Docker)
|
## Production (Docker)
|
||||||
|
|
||||||
|
Un **conteneur unique** : l'image builde le frontend Vue puis le fait servir
|
||||||
|
par le backend FastAPI (API + interface web sur le meme port). Pas de nginx.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make docker
|
make docker # podman-compose up --build
|
||||||
|
# ou : docker compose up --build
|
||||||
```
|
```
|
||||||
|
|
||||||
Accessible sur **http://localhost:8080**.
|
Accessible sur **http://localhost:8080**.
|
||||||
|
|
||||||
|
Les donnees (base SQLite + documents) sont declarees via `PLESNA_DATA_DIR`
|
||||||
|
(voir `docker-compose.yml`) et persistees dans le volume `./data`, donc
|
||||||
|
conservees entre les redemarrages du conteneur.
|
||||||
|
|
||||||
## Application de bureau (Windows, sans ligne de commande)
|
## Application de bureau (Windows, sans ligne de commande)
|
||||||
|
|
||||||
L'application peut etre empaquetee en **executable Windows autonome** : un seul
|
L'application peut etre empaquetee en **executable Windows autonome** : un seul
|
||||||
|
|||||||
@@ -1,3 +1,18 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
# --- Étape 1 : build du frontend Vue -----------------------------------------
|
||||||
|
# Le backend FastAPI sert lui-même le SPA (frontend/dist) : un seul conteneur
|
||||||
|
# suffit, pas de nginx séparé. On builde donc le frontend ici puis on copie le
|
||||||
|
# résultat dans l'image Python finale.
|
||||||
|
FROM node:22-alpine AS frontend
|
||||||
|
|
||||||
|
WORKDIR /frontend
|
||||||
|
COPY frontend/package.json frontend/package-lock.json* ./
|
||||||
|
RUN npm install
|
||||||
|
COPY frontend/ ./
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# --- Étape 2 : image applicative Python --------------------------------------
|
||||||
FROM python:3.12-slim
|
FROM python:3.12-slim
|
||||||
|
|
||||||
# pdfplumber est en Python pur : aucune dépendance système (plus de poppler).
|
# pdfplumber est en Python pur : aucune dépendance système (plus de poppler).
|
||||||
@@ -11,6 +26,11 @@ RUN uv sync --frozen --no-dev --no-install-project
|
|||||||
COPY src/ src/
|
COPY src/ src/
|
||||||
RUN uv sync --frozen --no-dev
|
RUN uv sync --frozen --no-dev
|
||||||
|
|
||||||
|
# Frontend buildé : servi par le backend via le fallback SPA (api/app.py).
|
||||||
|
COPY --from=frontend /frontend/dist/ frontend/dist/
|
||||||
|
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
CMD ["uv", "run", "plesna-gerance", "serve", "--host", "0.0.0.0"]
|
# --no-sync : ne pas re-résoudre/installer au démarrage (l'env est déjà figé
|
||||||
|
# par les `uv sync --frozen` ci-dessus). Sinon `uv run` réinstalle les deps dev.
|
||||||
|
CMD ["uv", "run", "--no-sync", "plesna-gerance", "serve", "--host", "0.0.0.0"]
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
services:
|
services:
|
||||||
backend:
|
app:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: backend.Dockerfile
|
dockerfile: backend.Dockerfile
|
||||||
|
ports:
|
||||||
|
# hôte:conteneur — l'app (API + interface web) écoute sur 8000
|
||||||
|
- "8080:8000"
|
||||||
volumes:
|
volumes:
|
||||||
|
# Persiste base SQLite + documents hors du conteneur.
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
environment:
|
environment:
|
||||||
- PLESNA_DB_PATH=/app/data/database.sqlite
|
# Déclare l'emplacement des données ; get_data_dir() en dérive
|
||||||
- PLESNA_STORAGE_PATH=/app/data/documents
|
# database.sqlite et documents/ (cf. src/plesna_gerance/paths.py).
|
||||||
restart: unless-stopped
|
- PLESNA_DATA_DIR=/app/data
|
||||||
|
|
||||||
frontend:
|
|
||||||
build:
|
|
||||||
context: ./frontend
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
ports:
|
|
||||||
- "8080:80"
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
node_modules
|
|
||||||
dist
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
FROM node:22-alpine AS build
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
COPY package.json package-lock.json* ./
|
|
||||||
RUN npm install
|
|
||||||
COPY . .
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
FROM nginx:alpine
|
|
||||||
COPY --from=build /app/dist /usr/share/nginx/html
|
|
||||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
|
||||||
EXPOSE 80
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 80;
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html;
|
|
||||||
|
|
||||||
# Proxy API requests to backend
|
|
||||||
location /api {
|
|
||||||
proxy_pass http://backend:8000;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
client_max_body_size 50M;
|
|
||||||
}
|
|
||||||
|
|
||||||
# SPA fallback
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user