feat: Ajout configuration Docker complète pour v2

 Fichiers Docker ajoutés:
- backend/Dockerfile: Image Python 3.11 avec uv et FastAPI
- frontend/Dockerfile: Build multi-stage avec Nginx
- docker-compose.yml: Orchestration complète des services
- frontend/nginx.conf: Configuration Nginx avec proxy API

📝 Documentation:
- DOCKER.md: Guide complet de déploiement Docker (monitoring, backup, prod)
- README.md: Section Docker ajoutée
- .env.docker: Template mis à jour pour v2

🔧 Configuration:
- .dockerignore pour backend et frontend
- Volume data/ pour la base de données
- Healthchecks pour les deux services
- Réseau bridge dédié

🚀 Démarrage simplifié:
  cp .env.docker .env
  docker-compose up -d

Accès: http://localhost (frontend) + http://localhost:8000 (API)
This commit is contained in:
2025-11-25 21:22:41 +01:00
parent 1f17b1e982
commit 634b6958bb
10 changed files with 683 additions and 12 deletions

View File

@@ -1,17 +1,26 @@
# Configuration pour Docker - COPIEZ CE FICHIER EN .env ET MODIFIEZ
# IMPORTANT: Générez une clé SECRET_KEY unique et sécurisée !
# Configuration Docker pour Notytex v2
# COPIEZ CE FICHIER EN .env ET MODIFIEZ LES VALEURS
# Clé secrète Flask (OBLIGATOIRE - minimum 32 caractères)
# Générez une nouvelle clé avec: python -c "import secrets; print(secrets.token_hex(32))"
SECRET_KEY=CHANGEZ-MOI-cle-secrete-unique-minimum-32-caracteres-obligatoire-docker
# ⚠️ IMPORTANT: Générez une clé SECRET_KEY unique et sécurisée !
# Commande: python -c "import secrets; print(secrets.token_hex(32))"
SECRET_KEY=CHANGEZ-MOI-cle-secrete-unique-minimum-32-caracteres-obligatoire
# Base de données (stockée dans le volume ./instance)
DATABASE_URL=sqlite:///instance/school_management.db
# Base de données (stockée dans le volume ./data)
DATABASE_URL=sqlite+aiosqlite:////data/school_management.db
# Configuration production
FLASK_ENV=production
DEBUG=false
# CORS - Ajustez selon vos domaines
CORS_ORIGINS=["http://localhost","http://localhost:80","https://votre-domaine.com"]
# Logging
LOG_LEVEL=INFO
# Configuration optionnelle
WTF_CSRF_TIME_LIMIT=3600
# Email (optionnel - pour l'envoi de bilans)
# SMTP_HOST=smtp.gmail.com
# SMTP_PORT=587
# SMTP_USERNAME=votre-email@gmail.com
# SMTP_PASSWORD=votre-mot-de-passe-app
# EMAIL_FROM=votre-email@gmail.com
# SMTP_USE_TLS=true
# Configuration production
DEBUG=false

4
.gitignore vendored
View File

@@ -79,6 +79,10 @@ logs/
.coverage
htmlcov/
# Docker data
data/
!data/.gitkeep
# Flask legacy
instance/
.webassets-cache

423
DOCKER.md Normal file
View File

@@ -0,0 +1,423 @@
# 🐳 Déploiement Docker - Notytex v2
Guide complet pour déployer Notytex avec Docker et Docker Compose.
---
## 🚀 Démarrage Rapide
### Prérequis
- Docker 20.10+
- Docker Compose 2.0+
### Installation en 3 commandes
```bash
# 1. Configurer l'environnement
cp .env.docker .env
# Éditez .env et changez SECRET_KEY !
# 2. Créer le répertoire de données
mkdir -p data
cp school_management.db data/
# 3. Démarrer les services
docker-compose up -d
```
**Accès :**
- Frontend : http://localhost
- API : http://localhost:8000
- Documentation API : http://localhost:8000/api/v2/docs
---
## 📂 Architecture Docker
```
┌─────────────────────────────────────────────────┐
│ Nginx:80 │
│ (Frontend Vue.js) │
└────────────────┬────────────────────────────────┘
│ Proxy /api → backend:8000
┌────────────────▼────────────────────────────────┐
│ FastAPI:8000 │
│ (Backend Python) │
└────────────────┬────────────────────────────────┘
│ SQLite
┌────────────────▼────────────────────────────────┐
│ Volume: ./data │
│ (Base de données SQLite) │
└─────────────────────────────────────────────────┘
```
---
## 🔧 Configuration
### Variables d'Environnement
Éditez le fichier `.env` :
```bash
# Clé secrète (OBLIGATOIRE - générez-en une nouvelle !)
SECRET_KEY=votre-cle-secrete-unique-min-32-chars
# Base de données
DATABASE_URL=sqlite+aiosqlite:////data/school_management.db
# CORS (ajoutez vos domaines)
CORS_ORIGINS=["http://localhost","https://votre-domaine.com"]
# Email (optionnel)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=votre-email@gmail.com
SMTP_PASSWORD=votre-mot-de-passe-app
EMAIL_FROM=votre-email@gmail.com
```
### Générer une SECRET_KEY
```bash
python -c "import secrets; print(secrets.token_hex(32))"
```
---
## 🛠️ Commandes Docker
### Démarrage
```bash
# Démarrer en arrière-plan
docker-compose up -d
# Voir les logs
docker-compose logs -f
# Logs d'un service spécifique
docker-compose logs -f backend
docker-compose logs -f frontend
```
### Arrêt
```bash
# Arrêter les services
docker-compose stop
# Arrêter et supprimer les conteneurs
docker-compose down
# Arrêter et supprimer tout (conteneurs + volumes)
docker-compose down -v
```
### Rebuild
```bash
# Rebuild après modification du code
docker-compose build
# Rebuild et redémarrage
docker-compose up -d --build
# Rebuild un service spécifique
docker-compose build backend
docker-compose up -d backend
```
### Inspection
```bash
# Statut des services
docker-compose ps
# Santé des services
docker-compose ps -a
# Entrer dans un conteneur
docker-compose exec backend sh
docker-compose exec frontend sh
```
---
## 🗄️ Gestion de la Base de Données
### Backup
```bash
# Créer un backup
docker-compose exec backend sh -c "cp /data/school_management.db /data/backup_$(date +%Y%m%d_%H%M%S).db"
# Ou depuis l'hôte
cp data/school_management.db data/backup_$(date +%Y%m%d_%H%M%S).db
```
### Restauration
```bash
# Restaurer depuis un backup
docker-compose stop backend
cp data/backup_YYYYMMDD_HHMMSS.db data/school_management.db
docker-compose start backend
```
### Migration depuis v1
```bash
# Si vous avez une base v1 Flask
cp instance/school_management.db data/school_management.db
docker-compose restart backend
```
---
## 🔍 Healthcheck
Les services incluent des healthchecks automatiques :
```bash
# Vérifier la santé du backend
curl http://localhost:8000/api/v2/health
# Vérifier la santé du frontend
curl http://localhost/
# Voir le statut Docker
docker-compose ps
```
**Réponse attendue du backend :**
```json
{
"status": "healthy",
"database": "connected",
"tables": 12,
"classes": 5,
"students": 155
}
```
---
## 🚨 Dépannage
### Le backend ne démarre pas
```bash
# Voir les logs
docker-compose logs backend
# Vérifier la configuration
docker-compose exec backend env | grep DATABASE_URL
# Recréer le conteneur
docker-compose up -d --force-recreate backend
```
### Le frontend ne charge pas
```bash
# Vérifier Nginx
docker-compose logs frontend
# Tester la connectivité au backend
docker-compose exec frontend curl http://backend:8000/api/v2/health
# Rebuild le frontend
docker-compose build frontend
docker-compose up -d frontend
```
### Problème de permissions (base de données)
```bash
# Ajuster les permissions
chmod 666 data/school_management.db
chmod 755 data/
```
### Les changements de code ne sont pas pris en compte
```bash
# Rebuild complet
docker-compose down
docker-compose build --no-cache
docker-compose up -d
```
---
## 🌐 Déploiement Production
### Configuration Nginx (hôte)
Si vous utilisez Nginx sur l'hôte pour le reverse proxy :
```nginx
server {
listen 80;
server_name notytex.example.com;
location / {
proxy_pass http://localhost:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
### HTTPS avec Let's Encrypt
```bash
# Installer certbot
sudo apt install certbot python3-certbot-nginx
# Obtenir un certificat
sudo certbot --nginx -d notytex.example.com
# Renouvellement automatique est configuré
```
### Systemd Service
Créez `/etc/systemd/system/notytex.service` :
```ini
[Unit]
Description=Notytex Docker Compose
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/path/to/notytex
ExecStart=/usr/bin/docker-compose up -d
ExecStop=/usr/bin/docker-compose down
[Install]
WantedBy=multi-user.target
```
Activer :
```bash
sudo systemctl enable notytex
sudo systemctl start notytex
```
---
## 📊 Monitoring
### Logs centralisés
```bash
# Tous les logs en temps réel
docker-compose logs -f
# Logs des dernières 24h
docker-compose logs --since 24h
# Recherche dans les logs
docker-compose logs | grep ERROR
```
### Métriques Docker
```bash
# Utilisation ressources
docker stats
# Espace disque
docker system df
# Nettoyage
docker system prune -a
```
---
## 🔐 Sécurité
### Checklist Production
- [ ] Changer `SECRET_KEY` (unique et aléatoire)
- [ ] Configurer CORS avec vos domaines réels
- [ ] Utiliser HTTPS en production
- [ ] Limiter les ports exposés (firewall)
- [ ] Mettre en place des backups automatiques
- [ ] Configurer des alertes monitoring
- [ ] Restreindre les permissions fichiers
- [ ] Mettre à jour régulièrement les images Docker
### Mise à jour des images de base
```bash
# Pull les dernières images
docker-compose pull
# Rebuild avec nouvelles images
docker-compose up -d --build
```
---
## 📦 Multi-environnements
### Développement
```bash
# Utiliser docker-compose.dev.yml
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up
```
### Production
```bash
# Utiliser docker-compose.prod.yml
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
```
---
## 🎯 Performances
### Optimisations
1. **Build multi-stage** : Réduit la taille des images
2. **Cache des dépendances** : Accélère les rebuilds
3. **Gzip Nginx** : Compression des assets
4. **Cache statique** : Headers cache 1 an pour JS/CSS
5. **Healthchecks** : Détection automatique des problèmes
### Ressources recommandées
- **Backend** : 512MB RAM, 0.5 CPU
- **Frontend** : 256MB RAM, 0.25 CPU
- **Total** : ~1GB RAM, 1 CPU pour 50 utilisateurs
---
## 📞 Support
En cas de problème :
1. Vérifiez les logs : `docker-compose logs`
2. Testez les healthchecks
3. Consultez la documentation : `README.md`
4. Vérifiez les issues GitHub
---
**Développé avec ❤️ pour simplifier le déploiement de Notytex**

View File

@@ -39,6 +39,21 @@ npm run dev
- **Documentation API** : http://localhost:8000/api/v2/docs
- **ReDoc** : http://localhost:8000/api/v2/redoc
### **Déploiement avec Docker** 🐳
```bash
# Configuration
cp .env.docker .env
# Éditez .env et changez SECRET_KEY
# Démarrage
docker-compose up -d
# Accès: http://localhost
```
📖 **Documentation complète** : [`DOCKER.md`](DOCKER.md)
---
## 🏗️ **Architecture Technique**

34
backend/.dockerignore Normal file
View File

@@ -0,0 +1,34 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
# Virtual environments
.venv/
venv/
env/
ENV/
# Tests
.pytest_cache/
.coverage
htmlcov/
# IDE
.vscode/
.idea/
*.swp
*.swo
# Environment
.env
.env.local
# Documentation
docs/
# Git
.git/
.gitignore

29
backend/Dockerfile Normal file
View File

@@ -0,0 +1,29 @@
# Dockerfile pour Backend FastAPI
FROM python:3.11-slim
# Variables d'environnement
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1
# Installer uv
RUN pip install uv
# Créer répertoire de travail
WORKDIR /app
# Copier les fichiers de dépendances
COPY pyproject.toml uv.lock ./
# Installer les dépendances
RUN uv sync --frozen
# Copier le code source
COPY . .
# Exposer le port
EXPOSE 8000
# Commande de démarrage
CMD ["uv", "run", "python", "-m", "uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000"]

55
docker-compose.yml Normal file
View File

@@ -0,0 +1,55 @@
version: '3.8'
services:
# Backend FastAPI
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: notytex-backend
restart: unless-stopped
ports:
- "8000:8000"
environment:
- DATABASE_URL=sqlite+aiosqlite:////data/school_management.db
- SECRET_KEY=${SECRET_KEY:-change-me-in-production-min-32-chars}
- CORS_ORIGINS=["http://localhost","http://localhost:80","http://localhost:3000"]
- LOG_LEVEL=INFO
volumes:
- ./data:/data
- ./backend:/app
networks:
- notytex-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/api/v2/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# Frontend Vue.js + Nginx
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: notytex-frontend
restart: unless-stopped
ports:
- "80:80"
depends_on:
- backend
networks:
- notytex-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/"]
interval: 30s
timeout: 10s
retries: 3
networks:
notytex-network:
driver: bridge
volumes:
data:
driver: local

29
frontend/.dockerignore Normal file
View File

@@ -0,0 +1,29 @@
# Node
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Build
dist/
.vite/
# Environment
.env.local
.env.*.local
# IDE
.vscode/
.idea/
*.swp
*.swo
# Tests
coverage/
# Git
.git/
.gitignore
# Logs
*.log

32
frontend/Dockerfile Normal file
View File

@@ -0,0 +1,32 @@
# Dockerfile pour Frontend Vue.js
# Stage 1: Build
FROM node:18-alpine AS builder
WORKDIR /app
# Copier package.json et package-lock.json
COPY package*.json ./
# Installer les dépendances
RUN npm ci
# Copier le code source
COPY . .
# Build de production
RUN npm run build
# Stage 2: Production avec Nginx
FROM nginx:alpine
# Copier le build depuis le stage précédent
COPY --from=builder /app/dist /usr/share/nginx/html
# Copier la configuration Nginx
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Exposer le port
EXPOSE 80
# Commande de démarrage
CMD ["nginx", "-g", "daemon off;"]

41
frontend/nginx.conf Normal file
View File

@@ -0,0 +1,41 @@
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json application/javascript;
# SPA routing - toutes les routes vers index.html
location / {
try_files $uri $uri/ /index.html;
}
# Proxy API vers le backend
location /api/ {
proxy_pass http://backend:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
# Cache pour les assets statiques
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Sécurité
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
}