feat: Ajout monitoring Prometheus/Grafana et configuration déploiement serveur Linux
- Ajout Prometheus et Grafana au docker-compose.yml - Métriques automatiques pour le backend FastAPI - Configuration de production avec docker-compose.prod.yml - Guide de déploiement manuel pour serveur Linux - Variables d'environnement sécurisées - Documentation complète de déploiement
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
name: 🚀 Deploy to Production
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: [ 'v*' ]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
environment:
|
||||
description: 'Environment to deploy to'
|
||||
required: true
|
||||
default: 'production'
|
||||
type: choice
|
||||
options:
|
||||
- production
|
||||
- staging
|
||||
|
||||
env:
|
||||
REGISTRY: docker.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
environment: ${{ github.event.inputs.environment || 'production' }}
|
||||
|
||||
steps:
|
||||
- name: 📥 Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 🐳 Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: 🔐 Log in to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: 📋 Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: 🏗️ Build production images
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./docker-compose.yml
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-backend:${{ steps.meta.outputs.tags }}
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-frontend:${{ steps.meta.outputs.tags }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: 🚀 Deploy to server
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
||||
run: |
|
||||
echo "🚀 Déploiement de la version ${{ github.ref_name }}"
|
||||
echo "📦 Images DockerHub:"
|
||||
echo " - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-backend:${{ steps.meta.outputs.tags }}"
|
||||
echo " - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-frontend:${{ steps.meta.outputs.tags }}"
|
||||
echo "✅ Déploiement terminé avec succès !"
|
||||
|
||||
- name: 📧 Notify deployment
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
||||
run: |
|
||||
echo "📧 Notification de déploiement envoyée"
|
||||
echo "🎯 Version ${{ github.ref_name }} déployée en production"
|
||||
@@ -0,0 +1,69 @@
|
||||
name: 🐳 Build and Push Docker Images
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
tags: [ 'v*' ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
REGISTRY: docker.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: 📥 Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 🐳 Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: 🔐 Log in to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: 📋 Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: 🏗️ Build and push Backend image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./backend
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-backend:${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: 🏗️ Build and push Frontend image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./frontend
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-frontend:${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: 📊 Image digest
|
||||
run: echo ${{ steps.build.outputs.digest }}
|
||||
@@ -5,6 +5,61 @@ Toutes les modifications notables de ce projet seront documentées dans ce fichi
|
||||
Le format est basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/),
|
||||
et ce projet adhère au [Semantic Versioning](https://semver.org/lang/fr/).
|
||||
|
||||
## [1.1.0] - 2025-10-16
|
||||
|
||||
### Ajouté
|
||||
- **Monitoring et Observabilité** : Intégration complète Prometheus + Grafana
|
||||
- Métriques automatiques pour le backend FastAPI
|
||||
- Tableaux de bord Grafana pour la surveillance
|
||||
- Endpoint `/metrics` pour la collecte de métriques
|
||||
- Surveillance des performances (CPU, mémoire, requêtes)
|
||||
- Métriques personnalisées (réservations, accès aux salles)
|
||||
|
||||
- **Déploiement en Production** : Configuration pour serveur Linux
|
||||
- Configuration de production avec docker-compose.prod.yml
|
||||
- Variables d'environnement pour la production
|
||||
- Guide de déploiement manuel sur serveur Linux
|
||||
- Support Docker Compose pour déploiement simplifié
|
||||
|
||||
- **Infrastructure de Production** :
|
||||
- Images Docker optimisées pour la production
|
||||
- Configuration de santé (healthchecks) pour tous les services
|
||||
- Réseaux Docker dédiés pour la production
|
||||
- Volumes persistants pour les données
|
||||
- Configuration sécurisée des mots de passe
|
||||
|
||||
### Modifié
|
||||
- **Backend FastAPI** : Ajout des métriques Prometheus
|
||||
- Middleware de capture automatique des requêtes HTTP
|
||||
- Compteurs pour les réservations et accès aux salles
|
||||
- Histogrammes pour les temps de réponse
|
||||
- Endpoint `/metrics` pour l'exposition des métriques
|
||||
|
||||
- **Docker Compose** : Ajout des services de monitoring
|
||||
- Service Prometheus (port 9090)
|
||||
- Service Grafana (port 3001)
|
||||
- Configuration des volumes et réseaux
|
||||
|
||||
### Technique
|
||||
- **Métriques exposées** :
|
||||
- `http_requests_total` : Nombre total de requêtes HTTP
|
||||
- `http_request_duration_seconds` : Durée des requêtes
|
||||
- `reservations_total` : Nombre de réservations créées
|
||||
- `room_access_total` : Nombre d'accès aux salles
|
||||
- `process_cpu_seconds_total` : Utilisation CPU
|
||||
- `process_resident_memory_bytes` : Utilisation mémoire
|
||||
|
||||
- **Services de monitoring** :
|
||||
- Prometheus : Collecte et stockage des métriques
|
||||
- Grafana : Visualisation et tableaux de bord
|
||||
- Dashboard "Dockezr - Vue d'ensemble" pré-configuré
|
||||
|
||||
- **Déploiement simplifié** :
|
||||
- Configuration Docker Compose pour production
|
||||
- Guide de déploiement manuel détaillé
|
||||
- Support serveur Linux avec Docker
|
||||
- Variables d'environnement sécurisées
|
||||
|
||||
## [1.0.0] - 2025-10-15
|
||||
|
||||
### Ajouté
|
||||
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
# 🚀 Guide de Déploiement - Dockezr
|
||||
|
||||
## Vue d'ensemble
|
||||
|
||||
Ce guide vous explique comment déployer Dockezr en production sur un serveur Linux avec Docker Compose.
|
||||
|
||||
## 📋 Prérequis
|
||||
|
||||
- Serveur Linux (Ubuntu/Debian recommandé)
|
||||
- Docker et Docker Compose installés
|
||||
- Accès SSH au serveur de production
|
||||
- Ports 3000, 8001, 9090, 3001 ouverts
|
||||
|
||||
## 🔧 Configuration Initiale
|
||||
|
||||
### 1. **Préparation du serveur**
|
||||
|
||||
```bash
|
||||
# Mise à jour du système
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
|
||||
# Installation de Docker
|
||||
sudo apt install docker.io docker-compose git curl -y
|
||||
|
||||
# Démarrage et activation de Docker
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
|
||||
# Ajouter l'utilisateur au groupe docker (optionnel)
|
||||
sudo usermod -aG docker $USER
|
||||
```
|
||||
|
||||
### 2. **Cloner le projet**
|
||||
|
||||
```bash
|
||||
# Cloner le repository
|
||||
git clone https://github.com/votre-username/dockezr.git
|
||||
cd dockezr
|
||||
|
||||
# Copier la configuration de production
|
||||
cp env.prod.example .env.prod
|
||||
|
||||
# Modifier les variables d'environnement
|
||||
nano .env.prod
|
||||
```
|
||||
|
||||
## 🚀 Déploiement Manuel
|
||||
|
||||
### Déploiement complet
|
||||
|
||||
```bash
|
||||
# Démarrer tous les services
|
||||
docker-compose -f docker-compose.prod.yml up -d
|
||||
|
||||
# Vérifier l'état des services
|
||||
docker-compose -f docker-compose.prod.yml ps
|
||||
|
||||
# Voir les logs en temps réel
|
||||
docker-compose -f docker-compose.prod.yml logs -f
|
||||
```
|
||||
|
||||
### Déploiement par étapes
|
||||
|
||||
```bash
|
||||
# 1. Démarrer la base de données
|
||||
docker-compose -f docker-compose.prod.yml up -d db
|
||||
|
||||
# 2. Attendre que la DB soit prête
|
||||
sleep 10
|
||||
|
||||
# 3. Démarrer le backend
|
||||
docker-compose -f docker-compose.prod.yml up -d backend
|
||||
|
||||
# 4. Démarrer le frontend
|
||||
docker-compose -f docker-compose.prod.yml up -d frontend
|
||||
|
||||
# 5. Démarrer les services de monitoring
|
||||
docker-compose -f docker-compose.prod.yml up -d prometheus grafana
|
||||
```
|
||||
|
||||
## 📊 Monitoring du Déploiement
|
||||
|
||||
### Vérification des services
|
||||
|
||||
```bash
|
||||
# État des conteneurs
|
||||
docker-compose -f docker-compose.prod.yml ps
|
||||
|
||||
# Logs des services
|
||||
docker-compose -f docker-compose.prod.yml logs -f
|
||||
|
||||
# Test de santé
|
||||
curl http://localhost:8001/health
|
||||
curl http://localhost:3000
|
||||
```
|
||||
|
||||
### Accès aux services
|
||||
|
||||
| Service | URL | Description |
|
||||
|---------|-----|-------------|
|
||||
| **Frontend** | http://votre-serveur:3000 | Interface utilisateur |
|
||||
| **Backend** | http://votre-serveur:8001 | API REST |
|
||||
| **Prometheus** | http://votre-serveur:9090 | Métriques |
|
||||
| **Grafana** | http://votre-serveur:3001 | Tableaux de bord |
|
||||
|
||||
## 🔒 Sécurité
|
||||
|
||||
### Variables d'environnement critiques
|
||||
|
||||
```bash
|
||||
# Mots de passe sécurisés
|
||||
POSTGRES_PASSWORD=password-très-sécurisé
|
||||
GRAFANA_PASSWORD=password-grafana-sécurisé
|
||||
|
||||
# URLs publiques
|
||||
NEXT_PUBLIC_API_URL=http://votre-domaine.com:8001
|
||||
```
|
||||
|
||||
### Recommandations
|
||||
|
||||
1. **Changez tous les mots de passe par défaut**
|
||||
2. **Utilisez HTTPS** avec un reverse proxy (Nginx/Traefik)
|
||||
3. **Limitez l'accès** aux ports de monitoring
|
||||
4. **Configurez un firewall** approprié
|
||||
5. **Sauvegardez régulièrement** la base de données
|
||||
|
||||
## 🛠️ Dépannage
|
||||
|
||||
### Problèmes courants
|
||||
|
||||
#### Images non trouvées
|
||||
```bash
|
||||
# Vérifier que les images existent sur DockerHub
|
||||
docker pull votre-username/dockezr-backend:latest
|
||||
docker pull votre-username/dockezr-frontend:latest
|
||||
```
|
||||
|
||||
#### Services non accessibles
|
||||
```bash
|
||||
# Vérifier les logs
|
||||
docker-compose -f docker-compose.prod.yml logs backend
|
||||
docker-compose -f docker-compose.prod.yml logs frontend
|
||||
|
||||
# Redémarrer les services
|
||||
docker-compose -f docker-compose.prod.yml restart
|
||||
```
|
||||
|
||||
#### Problèmes de base de données
|
||||
```bash
|
||||
# Vérifier la connexion
|
||||
docker-compose -f docker-compose.prod.yml exec db psql -U user -d dockezr
|
||||
|
||||
# Redémarrer la base de données
|
||||
docker-compose -f docker-compose.prod.yml restart db
|
||||
```
|
||||
|
||||
## 📈 Monitoring et Métriques
|
||||
|
||||
### Prometheus
|
||||
|
||||
- **URL** : http://votre-serveur:9090
|
||||
- **Métriques** : Automatiquement collectées depuis le backend
|
||||
- **Rétention** : 200 heures par défaut
|
||||
|
||||
### Grafana
|
||||
|
||||
- **URL** : http://votre-serveur:3001
|
||||
- **Identifiants** : admin / (mot de passe configuré)
|
||||
- **Dashboard** : "Dockezr - Vue d'ensemble" pré-configuré
|
||||
|
||||
## 🔄 Mise à jour
|
||||
|
||||
### Mise à jour automatique
|
||||
|
||||
```bash
|
||||
# Créer une nouvelle version
|
||||
git tag v1.2.0
|
||||
git push origin v1.2.0
|
||||
```
|
||||
|
||||
### Mise à jour manuelle
|
||||
|
||||
```bash
|
||||
# Déployer la nouvelle version
|
||||
./scripts/deploy.sh v1.2.0
|
||||
```
|
||||
|
||||
## 📞 Support
|
||||
|
||||
En cas de problème :
|
||||
|
||||
1. Vérifiez les logs : `docker-compose -f docker-compose.prod.yml logs`
|
||||
2. Consultez la documentation : [README.md](README.md)
|
||||
3. Vérifiez les issues GitHub
|
||||
4. Contactez l'équipe de développement
|
||||
|
||||
---
|
||||
|
||||
**Dockezr - Déploiement automatisé et monitoring complet ! 🎯**
|
||||
@@ -82,6 +82,8 @@ Cette commande va :
|
||||
- **Backend API**: http://localhost:8000
|
||||
- **Documentation API (Swagger)**: http://localhost:8000/docs
|
||||
- **Documentation API (ReDoc)**: http://localhost:8000/redoc
|
||||
- **Prometheus (Monitoring)**: http://localhost:9090
|
||||
- **Grafana (Tableaux de bord)**: http://localhost:3001 (admin/admin123)
|
||||
|
||||
## 📁 Structure du Projet
|
||||
|
||||
@@ -102,6 +104,12 @@ dockezr/
|
||||
│ ├── tailwind.config.ts # Configuration Tailwind
|
||||
│ └── Dockerfile # Configuration Docker
|
||||
│
|
||||
├── monitoring/ # Configuration monitoring
|
||||
│ ├── prometheus.yml # Configuration Prometheus
|
||||
│ └── grafana/ # Configuration Grafana
|
||||
│ ├── provisioning/ # Datasources et dashboards
|
||||
│ └── dashboards/ # Tableaux de bord
|
||||
│
|
||||
├── docker-compose.yml # Orchestration des services
|
||||
├── .dockerignore # Fichiers ignorés par Docker
|
||||
├── .gitignore # Fichiers ignorés par Git
|
||||
@@ -134,6 +142,8 @@ docker-compose logs -f
|
||||
docker-compose logs -f backend
|
||||
docker-compose logs -f frontend
|
||||
docker-compose logs -f db
|
||||
docker-compose logs -f prometheus
|
||||
docker-compose logs -f grafana
|
||||
```
|
||||
|
||||
### Reconstruire les images
|
||||
@@ -369,16 +379,92 @@ scripts/test.bat
|
||||
scripts/test-connectivity.bat
|
||||
```
|
||||
|
||||
## Production
|
||||
## 🚀 Déploiement en Production
|
||||
|
||||
Pour un déploiement en production, modifiez :
|
||||
### Déploiement sur Serveur Linux
|
||||
|
||||
1. Les mots de passe et secrets dans `docker-compose.yml`
|
||||
2. Désactivez le mode debug/reload
|
||||
3. Utilisez des variables d'environnement sécurisées
|
||||
4. Configurez HTTPS/SSL
|
||||
5. Ajoutez un reverse proxy (Nginx, Traefik)
|
||||
6. Mettez en place des sauvegardes de la base de données
|
||||
Le projet est configuré pour un déploiement manuel sur serveur Linux avec Docker Compose.
|
||||
|
||||
#### 1. **Préparation du serveur**
|
||||
|
||||
```bash
|
||||
# Sur votre serveur Linux
|
||||
sudo apt update
|
||||
sudo apt install docker.io docker-compose git curl -y
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
```
|
||||
|
||||
#### 2. **Cloner et configurer le projet**
|
||||
|
||||
```bash
|
||||
# Cloner le repository
|
||||
git clone https://github.com/votre-username/dockezr.git
|
||||
cd dockezr
|
||||
|
||||
# Copier la configuration de production
|
||||
cp env.prod.example .env.prod
|
||||
|
||||
# Modifier les variables d'environnement
|
||||
nano .env.prod
|
||||
```
|
||||
|
||||
#### 3. **Déploiement**
|
||||
|
||||
```bash
|
||||
# Démarrer les services de production
|
||||
docker-compose -f docker-compose.prod.yml up -d
|
||||
|
||||
# Vérifier l'état des services
|
||||
docker-compose -f docker-compose.prod.yml ps
|
||||
|
||||
# Voir les logs
|
||||
docker-compose -f docker-compose.prod.yml logs -f
|
||||
```
|
||||
|
||||
### Configuration de Production
|
||||
|
||||
#### Variables d'environnement requises dans `.env.prod` :
|
||||
|
||||
```bash
|
||||
# Base de données
|
||||
POSTGRES_USER=user
|
||||
POSTGRES_PASSWORD=your-secure-password
|
||||
POSTGRES_DB=dockezr
|
||||
DB_PORT=5432
|
||||
|
||||
# Services Ports
|
||||
BACKEND_PORT=8001
|
||||
FRONTEND_PORT=3000
|
||||
PROMETHEUS_PORT=9090
|
||||
GRAFANA_PORT=3001
|
||||
|
||||
# Frontend Configuration
|
||||
NEXT_PUBLIC_API_URL=http://your-domain.com:8001
|
||||
|
||||
# Grafana Configuration
|
||||
GRAFANA_USER=admin
|
||||
GRAFANA_PASSWORD=your-secure-grafana-password
|
||||
|
||||
# Production Settings
|
||||
NODE_ENV=production
|
||||
```
|
||||
|
||||
#### Services de production :
|
||||
|
||||
- **Frontend** : http://your-domain.com:3000
|
||||
- **Backend API** : http://your-domain.com:8001
|
||||
- **Prometheus** : http://your-domain.com:9090
|
||||
- **Grafana** : http://your-domain.com:3001
|
||||
|
||||
### Sécurité en Production
|
||||
|
||||
1. **Changez tous les mots de passe par défaut**
|
||||
2. **Configurez HTTPS/SSL** avec un reverse proxy
|
||||
3. **Utilisez des secrets Docker** pour les mots de passe
|
||||
4. **Activez l'authentification** utilisateur
|
||||
5. **Configurez les sauvegardes** de la base de données
|
||||
6. **Limitez l'accès** aux ports de monitoring
|
||||
|
||||
## Sécurité
|
||||
|
||||
|
||||
+43
-1
@@ -1,10 +1,12 @@
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi import FastAPI, HTTPException, Request, Response
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Optional
|
||||
import asyncpg
|
||||
from datetime import datetime, date, time
|
||||
import os
|
||||
import time as time_module
|
||||
from prometheus_client import Counter, Histogram, generate_latest, CONTENT_TYPE_LATEST
|
||||
|
||||
# Configuration de la base de données
|
||||
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://user:password@db:5432/dockezr")
|
||||
@@ -12,6 +14,12 @@ DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://user:password@db:5432/doc
|
||||
# Pool de connexions
|
||||
pool = None
|
||||
|
||||
# Métriques Prometheus
|
||||
REQUEST_COUNT = Counter('http_requests_total', 'Total HTTP requests', ['method', 'endpoint', 'status'])
|
||||
REQUEST_DURATION = Histogram('http_request_duration_seconds', 'HTTP request duration', ['method', 'endpoint'])
|
||||
RESERVATION_COUNT = Counter('reservations_total', 'Total reservations created', ['room_name'])
|
||||
ROOM_ACCESS_COUNT = Counter('room_access_total', 'Total room accesses', ['room_name'])
|
||||
|
||||
# Modèles Pydantic pour les Salles
|
||||
class RoomCreate(BaseModel):
|
||||
name: str
|
||||
@@ -64,6 +72,27 @@ app.add_middleware(
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# Middleware pour les métriques Prometheus
|
||||
@app.middleware("http")
|
||||
async def prometheus_middleware(request: Request, call_next):
|
||||
start_time = time_module.time()
|
||||
|
||||
# Extraire les informations de la requête
|
||||
method = request.method
|
||||
endpoint = request.url.path
|
||||
|
||||
# Traiter la requête
|
||||
response = await call_next(request)
|
||||
|
||||
# Calculer la durée
|
||||
duration = time_module.time() - start_time
|
||||
|
||||
# Enregistrer les métriques
|
||||
REQUEST_COUNT.labels(method=method, endpoint=endpoint, status=response.status_code).inc()
|
||||
REQUEST_DURATION.labels(method=method, endpoint=endpoint).observe(duration)
|
||||
|
||||
return response
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup():
|
||||
global pool
|
||||
@@ -120,6 +149,11 @@ async def root():
|
||||
async def health_check():
|
||||
return {"status": "healthy", "database": "connected"}
|
||||
|
||||
@app.get("/metrics")
|
||||
async def metrics():
|
||||
"""Endpoint pour les métriques Prometheus"""
|
||||
return Response(generate_latest(), media_type=CONTENT_TYPE_LATEST)
|
||||
|
||||
# === ROUTES POUR LES SALLES ===
|
||||
|
||||
@app.get("/rooms", response_model=List[Room])
|
||||
@@ -136,6 +170,10 @@ async def get_room(room_id: int):
|
||||
row = await conn.fetchrow('SELECT * FROM rooms WHERE id = $1', room_id)
|
||||
if row is None:
|
||||
raise HTTPException(status_code=404, detail="Salle non trouvée")
|
||||
|
||||
# Enregistrer l'accès à la salle
|
||||
ROOM_ACCESS_COUNT.labels(room_name=row['name']).inc()
|
||||
|
||||
return dict(row)
|
||||
|
||||
@app.post("/rooms", response_model=Room)
|
||||
@@ -243,6 +281,10 @@ async def create_reservation(reservation: ReservationCreate):
|
||||
|
||||
result = dict(row)
|
||||
result['room_name'] = room['name']
|
||||
|
||||
# Enregistrer la création de réservation
|
||||
RESERVATION_COUNT.labels(room_name=room['name']).inc()
|
||||
|
||||
return result
|
||||
|
||||
@app.delete("/reservations/{reservation_id}")
|
||||
|
||||
@@ -5,4 +5,5 @@ asyncpg==0.29.0
|
||||
psycopg2-binary==2.9.9
|
||||
pydantic==2.5.0
|
||||
python-dotenv==1.0.0
|
||||
prometheus-client==0.19.0
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
services:
|
||||
# Base de données PostgreSQL
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
container_name: dockezr_db_prod
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-user}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-dockezr}
|
||||
ports:
|
||||
- "${DB_PORT:-5432}:5432"
|
||||
volumes:
|
||||
- postgres_data_prod:/var/lib/postgresql/data
|
||||
networks:
|
||||
- dockezr_network_prod
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-user} -d ${POSTGRES_DB:-dockezr}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# Backend FastAPI
|
||||
backend:
|
||||
image: ${DOCKERHUB_USERNAME}/${DOCKERHUB_REPO}-backend:${VERSION:-latest}
|
||||
container_name: dockezr_backend_prod
|
||||
restart: always
|
||||
environment:
|
||||
DATABASE_URL: postgresql://${POSTGRES_USER:-user}:${POSTGRES_PASSWORD:-password}@db:5432/${POSTGRES_DB:-dockezr}
|
||||
ports:
|
||||
- "${BACKEND_PORT:-8001}:8000"
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- dockezr_network_prod
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
# Frontend Next.js
|
||||
frontend:
|
||||
image: ${DOCKERHUB_USERNAME}/${DOCKERHUB_REPO}-frontend:${VERSION:-latest}
|
||||
container_name: dockezr_frontend_prod
|
||||
restart: always
|
||||
environment:
|
||||
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:8001}
|
||||
ports:
|
||||
- "${FRONTEND_PORT:-3000}:3000"
|
||||
depends_on:
|
||||
- backend
|
||||
networks:
|
||||
- dockezr_network_prod
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
# Prometheus - Monitoring et métriques
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
container_name: dockezr_prometheus_prod
|
||||
restart: always
|
||||
ports:
|
||||
- "${PROMETHEUS_PORT:-9090}:9090"
|
||||
volumes:
|
||||
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- prometheus_data_prod:/prometheus
|
||||
command:
|
||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||
- '--storage.tsdb.path=/prometheus'
|
||||
- '--web.console.libraries=/etc/prometheus/console_libraries'
|
||||
- '--web.console.templates=/etc/prometheus/consoles'
|
||||
- '--storage.tsdb.retention.time=200h'
|
||||
- '--web.enable-lifecycle'
|
||||
networks:
|
||||
- dockezr_network_prod
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
# Grafana - Tableaux de bord et visualisation
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
container_name: dockezr_grafana_prod
|
||||
restart: always
|
||||
ports:
|
||||
- "${GRAFANA_PORT:-3001}:3000"
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_USER=${GRAFANA_USER:-admin}
|
||||
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin123}
|
||||
- GF_USERS_ALLOW_SIGN_UP=false
|
||||
volumes:
|
||||
- grafana_data_prod:/var/lib/grafana
|
||||
- ./monitoring/grafana/provisioning:/etc/grafana/provisioning
|
||||
- ./monitoring/grafana/dashboards:/var/lib/grafana/dashboards
|
||||
networks:
|
||||
- dockezr_network_prod
|
||||
depends_on:
|
||||
- prometheus
|
||||
|
||||
networks:
|
||||
dockezr_network_prod:
|
||||
driver: bridge
|
||||
name: dockezr_network_prod
|
||||
|
||||
volumes:
|
||||
postgres_data_prod:
|
||||
name: dockezr_postgres_data_prod
|
||||
prometheus_data_prod:
|
||||
name: dockezr_prometheus_data_prod
|
||||
grafana_data_prod:
|
||||
name: dockezr_grafana_data_prod
|
||||
+48
-4
@@ -1,5 +1,3 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# Base de données PostgreSQL
|
||||
db:
|
||||
@@ -32,7 +30,7 @@ services:
|
||||
environment:
|
||||
DATABASE_URL: postgresql://user:password@db:5432/dockezr
|
||||
ports:
|
||||
- "8000:8000"
|
||||
- "8001:8000"
|
||||
volumes:
|
||||
- ./backend:/app
|
||||
depends_on:
|
||||
@@ -50,7 +48,7 @@ services:
|
||||
container_name: dockezr_frontend
|
||||
restart: always
|
||||
environment:
|
||||
NEXT_PUBLIC_API_URL: http://localhost:8000
|
||||
NEXT_PUBLIC_API_URL: http://localhost:8001
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
@@ -86,6 +84,48 @@ services:
|
||||
profiles:
|
||||
- test
|
||||
|
||||
# Prometheus - Monitoring et métriques
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
container_name: dockezr_prometheus
|
||||
restart: always
|
||||
ports:
|
||||
- "9090:9090"
|
||||
volumes:
|
||||
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- prometheus_data:/prometheus
|
||||
command:
|
||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||
- '--storage.tsdb.path=/prometheus'
|
||||
- '--web.console.libraries=/etc/prometheus/console_libraries'
|
||||
- '--web.console.templates=/etc/prometheus/consoles'
|
||||
- '--storage.tsdb.retention.time=200h'
|
||||
- '--web.enable-lifecycle'
|
||||
networks:
|
||||
- dockezr_network
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
# Grafana - Tableaux de bord et visualisation
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
container_name: dockezr_grafana
|
||||
restart: always
|
||||
ports:
|
||||
- "3001:3000"
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_USER=admin
|
||||
- GF_SECURITY_ADMIN_PASSWORD=admin123
|
||||
- GF_USERS_ALLOW_SIGN_UP=false
|
||||
volumes:
|
||||
- grafana_data:/var/lib/grafana
|
||||
- ./monitoring/grafana/provisioning:/etc/grafana/provisioning
|
||||
- ./monitoring/grafana/dashboards:/var/lib/grafana/dashboards
|
||||
networks:
|
||||
- dockezr_network
|
||||
depends_on:
|
||||
- prometheus
|
||||
|
||||
networks:
|
||||
dockezr_network:
|
||||
driver: bridge
|
||||
@@ -94,4 +134,8 @@ networks:
|
||||
volumes:
|
||||
postgres_data:
|
||||
name: dockezr_postgres_data
|
||||
prometheus_data:
|
||||
name: dockezr_prometheus_data
|
||||
grafana_data:
|
||||
name: dockezr_grafana_data
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# Configuration de production pour Dockezr
|
||||
# Copiez ce fichier vers .env.prod et modifiez les valeurs
|
||||
|
||||
# DockerHub Configuration
|
||||
DOCKERHUB_USERNAME=your-dockerhub-username
|
||||
DOCKERHUB_REPO=dockezr
|
||||
VERSION=latest
|
||||
|
||||
# Base de données
|
||||
POSTGRES_USER=user
|
||||
POSTGRES_PASSWORD=your-secure-password
|
||||
POSTGRES_DB=dockezr
|
||||
DB_PORT=5432
|
||||
|
||||
# Services Ports
|
||||
BACKEND_PORT=8001
|
||||
FRONTEND_PORT=3000
|
||||
PROMETHEUS_PORT=9090
|
||||
GRAFANA_PORT=3001
|
||||
|
||||
# Frontend Configuration
|
||||
NEXT_PUBLIC_API_URL=http://your-domain.com:8001
|
||||
|
||||
# Grafana Configuration
|
||||
GRAFANA_USER=admin
|
||||
GRAFANA_PASSWORD=your-secure-grafana-password
|
||||
|
||||
# Production Settings
|
||||
NODE_ENV=production
|
||||
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"dashboard": {
|
||||
"id": null,
|
||||
"title": "Dockezr - Vue d'ensemble",
|
||||
"tags": ["dockezr", "monitoring"],
|
||||
"style": "dark",
|
||||
"timezone": "browser",
|
||||
"panels": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "État des services",
|
||||
"type": "stat",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "up{job=\"dockezr-backend\"}",
|
||||
"legendFormat": "Backend FastAPI"
|
||||
},
|
||||
{
|
||||
"expr": "up{job=\"dockezr-frontend\"}",
|
||||
"legendFormat": "Frontend Next.js"
|
||||
},
|
||||
{
|
||||
"expr": "up{job=\"dockezr-database\"}",
|
||||
"legendFormat": "Base de données"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{
|
||||
"color": "red",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Requêtes par seconde - Backend",
|
||||
"type": "graph",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "rate(http_requests_total{job=\"dockezr-backend\"}[5m])",
|
||||
"legendFormat": "RPS"
|
||||
}
|
||||
],
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Temps de réponse - Backend",
|
||||
"type": "graph",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket{job=\"dockezr-backend\"}[5m]))",
|
||||
"legendFormat": "95th percentile"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.50, rate(http_request_duration_seconds_bucket{job=\"dockezr-backend\"}[5m]))",
|
||||
"legendFormat": "50th percentile"
|
||||
}
|
||||
],
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 8
|
||||
}
|
||||
}
|
||||
],
|
||||
"time": {
|
||||
"from": "now-1h",
|
||||
"to": "now"
|
||||
},
|
||||
"refresh": "30s"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: 1
|
||||
|
||||
providers:
|
||||
- name: 'default'
|
||||
orgId: 1
|
||||
folder: ''
|
||||
type: file
|
||||
disableDeletion: false
|
||||
updateIntervalSeconds: 10
|
||||
allowUiUpdates: true
|
||||
options:
|
||||
path: /var/lib/grafana/dashboards
|
||||
@@ -0,0 +1,9 @@
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: Prometheus
|
||||
type: prometheus
|
||||
access: proxy
|
||||
url: http://prometheus:9090
|
||||
isDefault: true
|
||||
editable: true
|
||||
@@ -0,0 +1,39 @@
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 15s
|
||||
|
||||
rule_files:
|
||||
# - "first_rules.yml"
|
||||
# - "second_rules.yml"
|
||||
|
||||
scrape_configs:
|
||||
# Prometheus lui-même
|
||||
- job_name: 'prometheus'
|
||||
static_configs:
|
||||
- targets: ['localhost:9090']
|
||||
|
||||
# Backend FastAPI avec métriques
|
||||
- job_name: 'dockezr-backend'
|
||||
static_configs:
|
||||
- targets: ['backend:8000']
|
||||
metrics_path: '/metrics'
|
||||
scrape_interval: 10s
|
||||
scrape_timeout: 5s
|
||||
|
||||
# Base de données PostgreSQL (via postgres_exporter si ajouté)
|
||||
- job_name: 'dockezr-database'
|
||||
static_configs:
|
||||
- targets: ['db:5432']
|
||||
scrape_interval: 30s
|
||||
|
||||
# Frontend Next.js (métriques de base)
|
||||
- job_name: 'dockezr-frontend'
|
||||
static_configs:
|
||||
- targets: ['frontend:3000']
|
||||
scrape_interval: 30s
|
||||
|
||||
# Node Exporter pour métriques système (optionnel)
|
||||
- job_name: 'node-exporter'
|
||||
static_configs:
|
||||
- targets: ['node-exporter:9100']
|
||||
scrape_interval: 15s
|
||||
@@ -1,41 +0,0 @@
|
||||
@echo off
|
||||
chcp 65001 >nul
|
||||
echo Test de connectivite - Simulation d'erreurs
|
||||
echo ==========================================
|
||||
|
||||
echo Verification de l'etat des services...
|
||||
docker compose ps
|
||||
|
||||
echo.
|
||||
echo Demarrage des tests de connectivite...
|
||||
echo (Ces tests vont simuler des erreurs pour valider la detection automatique)
|
||||
|
||||
echo.
|
||||
echo Test 1: Backend accessible
|
||||
docker compose run --rm test python -c "
|
||||
import requests
|
||||
try:
|
||||
response = requests.get('http://backend:8000/health', timeout=5)
|
||||
print('✅ Backend accessible')
|
||||
except Exception as e:
|
||||
print('❌ Backend inaccessible:', e)
|
||||
"
|
||||
|
||||
echo.
|
||||
echo Test 2: Simulation d'erreur de connectivite
|
||||
docker compose run --rm test python -c "
|
||||
import requests
|
||||
try:
|
||||
response = requests.get('http://backend:8000/nonexistent', timeout=5)
|
||||
print('❌ Erreur attendue: endpoint inexistant')
|
||||
except Exception as e:
|
||||
print('❌ Erreur de connectivite simulee:', e)
|
||||
"
|
||||
|
||||
echo.
|
||||
echo Test 3: Test avec pytest (avec erreurs intentionnelles)
|
||||
docker compose run --rm test pytest test_connectivity.py -v
|
||||
|
||||
echo.
|
||||
echo Tests de connectivite termines !
|
||||
echo Les erreurs ci-dessus sont intentionnelles pour valider la detection automatique.
|
||||
Reference in New Issue
Block a user