Compare commits

...

3 Commits

Author SHA1 Message Date
Waloshi6
908c25840e bb 2026-02-08 14:41:38 +01:00
Waloshi6
4723f4ebb9 Merge branch 'main' of https://git.bonisco.fr/OrgaDevops/Tuto-Devops-A---Z 2026-02-08 14:38:44 +01:00
Waloshi6
7377c00a47 aa 2026-02-08 14:34:23 +01:00
15 changed files with 263 additions and 198 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*.log
manifest-*
*.bak

View File

@@ -16,4 +16,7 @@
- se connecter pour ouvrir l'accès ==> "url = https://git..." (url ==> C:\DevOpsProject\.git\config) - se connecter pour ouvrir l'accès ==> "url = https://git..." (url ==> C:\DevOpsProject\.git\config)
- "git push origin main" - "git push origin main"
# Puller une partie de projet modifié en preservant les modifs non pushé
-
-

View File

@@ -1 +1 @@
MANIFEST-000096 MANIFEST-000114

View File

@@ -1 +1 @@
MANIFEST-000094 MANIFEST-000112

View File

@@ -415,3 +415,93 @@
13:52:44.428084 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00] 13:52:44.428084 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
13:52:44.486849 db@janitor F·3 G·0 13:52:44.486849 db@janitor F·3 G·0
13:52:44.487042 db@open done T·69.246442ms 13:52:44.487042 db@open done T·69.246442ms
=============== Feb 5, 2026 (UTC) ===============
15:51:14.399455 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
15:51:14.439535 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
15:51:14.440100 db@open opening
15:51:14.443037 journal@recovery F·1
15:51:14.444002 journal@recovery recovering @93
15:51:14.457130 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
15:51:14.511329 db@janitor F·3 G·0
15:51:14.511866 db@open done T·71.613432ms
=============== Feb 6, 2026 (UTC) ===============
10:49:29.095596 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
10:49:29.131170 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
10:49:29.131550 db@open opening
10:49:29.135461 journal@recovery F·1
10:49:29.135730 journal@recovery recovering @95
10:49:29.141437 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
10:49:29.199095 db@janitor F·3 G·0
10:49:29.199560 db@open done T·67.8483ms
=============== Feb 6, 2026 (UTC) ===============
10:53:40.580960 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
10:53:40.591365 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
10:53:40.591700 db@open opening
10:53:40.593746 journal@recovery F·1
10:53:40.594013 journal@recovery recovering @97
10:53:40.604447 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
10:53:40.712208 db@janitor F·3 G·0
10:53:40.712621 db@open done T·120.78394ms
=============== Feb 6, 2026 (UTC) ===============
10:57:24.598143 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
10:57:24.616721 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
10:57:24.617237 db@open opening
10:57:24.618928 journal@recovery F·1
10:57:24.619220 journal@recovery recovering @99
10:57:24.622811 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
10:57:24.658530 db@janitor F·3 G·0
10:57:24.658711 db@open done T·41.279095ms
=============== Feb 6, 2026 (UTC) ===============
11:00:06.298412 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
11:00:06.310703 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
11:00:06.311328 db@open opening
11:00:06.316598 journal@recovery F·1
11:00:06.317192 journal@recovery recovering @101
11:00:06.325703 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
11:00:06.374535 db@janitor F·3 G·0
11:00:06.374849 db@open done T·63.190584ms
=============== Feb 6, 2026 (UTC) ===============
11:50:03.854543 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
11:50:03.864227 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
11:50:03.865796 db@open opening
11:50:03.872207 journal@recovery F·1
11:50:03.872558 journal@recovery recovering @103
11:50:03.876753 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
11:50:03.949425 db@janitor F·3 G·0
11:50:03.950338 db@open done T·84.322748ms
=============== Feb 6, 2026 (UTC) ===============
12:45:29.925234 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
12:45:29.952459 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
12:45:29.953662 db@open opening
12:45:29.959031 journal@recovery F·1
12:45:29.959375 journal@recovery recovering @105
12:45:29.963600 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
12:45:30.026778 db@janitor F·3 G·0
12:45:30.027106 db@open done T·73.277756ms
=============== Feb 7, 2026 (UTC) ===============
15:37:46.707349 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
15:37:46.739671 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
15:37:46.740550 db@open opening
15:37:46.745371 journal@recovery F·1
15:37:46.745766 journal@recovery recovering @107
15:37:46.751116 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
15:37:46.811638 db@janitor F·3 G·0
15:37:46.811822 db@open done T·70.8136ms
=============== Feb 7, 2026 (UTC) ===============
15:41:07.560631 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
15:41:07.573670 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
15:41:07.574246 db@open opening
15:41:07.576253 journal@recovery F·1
15:41:07.576509 journal@recovery recovering @109
15:41:07.579359 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
15:41:07.617133 db@janitor F·3 G·0
15:41:07.617309 db@open done T·42.89556ms
=============== Feb 8, 2026 (UTC) ===============
13:10:57.397891 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
13:10:57.432913 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
13:10:57.435331 db@open opening
13:10:57.437339 journal@recovery F·1
13:10:57.437654 journal@recovery recovering @111
13:10:57.440763 version@stat F·[0 1] S·577B[0B 577B] Sc·[0.00 0.00]
13:10:57.485091 db@janitor F·3 G·0
13:10:57.485346 db@open done T·49.7959ms

112
readme.md
View File

@@ -47,8 +47,18 @@ Original pourrit: https://cloud.bonisco.fr/s/Cb2bFdLXeFEFcLm
Ouvrir PowerShell en tant qu'ADMINISTRATEUR (clic droit → Exécuter en tant qu'administrateur) Ouvrir PowerShell en tant qu'ADMINISTRATEUR (clic droit → Exécuter en tant qu'administrateur)
1. Activer les fonctionnalités Windows nécessaires #🚀 TP DevOps Windows - Stack Complète Locale (Corrigé & Optimisé)
```
#📋 PRÉ-REQUIS WINDOWS - Installation Pas à Pas
Avant tout, bien penser à ACTIVER la fonction de VIRTUALISATION dans le BIOS du systeme de votre pc
#🔧 1. Préparation du système (PowerShell Administrateur)
# Ouvrir PowerShell en tant qu'ADMINISTRATEUR (clic droit → Exécuter en tant qu'administrateur)
# 1. Activer les fonctionnalités Windows nécessaires
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform
``` ```
@@ -63,8 +73,8 @@ wsl --set-default-version 2
4. Redémarrer l'ordinateur (OBLIGATOIRE) 4. Redémarrer l'ordinateur (OBLIGATOIRE)
``` ```
Restart-Computer Restart-Computer
```
### 📥 2. Installation des outils (après redémarrage) #📥 2. Installation des outils (après redémarrage)
1. Installer Chocolatey (package manager Windows) 1. Installer Chocolatey (package manager Windows)
``` ```
@@ -75,9 +85,9 @@ iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocola
2. Installer tous les outils 2. Installer tous les outils
``` ```
choco install -y git docker-desktop vscode kubernetes-cli minikube terraform helm postman choco install -y git docker-desktop vscode kubernetes-cli minikube terraform helm postman
```
3. Configuration WSL2 et Ubuntu #🐧 3. Configuration WSL2 et Ubuntu
```
# Vérifier l'installation WSL # Vérifier l'installation WSL
wsl --list --verbose wsl --list --verbose
# Doit afficher : Ubuntu-22.04 Running 2 # Doit afficher : Ubuntu-22.04 Running 2
@@ -98,10 +108,11 @@ Créer un alias pratique
echo "alias k=kubectl" >> ~/.bashrc echo "alias k=kubectl" >> ~/.bashrc
source ~/.bashrc source ~/.bashrc
exit # Retour à PowerShell exit # Retour à PowerShell
```
## 🐋 ÉTAPE 1 : CONFIGURATION DOCKER DESKTOP
### ⚙️ Configuration manuelle obligatoire : #🐋 ÉTAPE 1 : CONFIGURATION DOCKER DESKTOP
#⚙️ Configuration manuelle obligatoire :
Ouvrir Docker Desktop après installation Ouvrir Docker Desktop après installation
Settings → General : Settings → General :
@@ -131,10 +142,12 @@ docker run hello-world
Vérifier l'intégration WSL2 Vérifier l'intégration WSL2
``` ```
wsl -d Ubuntu-22.04 -e docker version wsl -d Ubuntu-22.04 -e docker version
``` # Doit fonctionner sans erreur
Doit fonctionner sans erreur
*📁 ÉTAPE 2 : STRUCTURE DU PROJET OPTIMISÉE
*🗂️ Création de la structure : #📁 ÉTAPE 2 : STRUCTURE DU PROJET OPTIMISÉE
#🗂️ Création de la structure :
Créer le dossier principal Créer le dossier principal
``` ```
@@ -173,11 +186,14 @@ C:\DevOpsProject\
├── .github\workflows\ # CI/CD ├── .github\workflows\ # CI/CD
├── config\ # Fichiers de config ├── config\ # Fichiers de config
└── docs\ # Documentation └── docs\ # Documentation
```
## 🐍 ÉTAPE 3 : APPLICATION PYTHON CORRIGÉE
### 3.1 Fichier : `src\app\requirements.txt` #🐍 ÉTAPE 3 : APPLICATION PYTHON CORRIGÉE
```
#3.1 Fichier : src\app\requirements.txt
# commentaire de Oualim : Ce fichier installera les dépendances dans le conteneur, pas sur votre machine
fastapi==0.104.1 fastapi==0.104.1
uvicorn[standard]==0.24.0 uvicorn[standard]==0.24.0
pydantic==2.5.0 pydantic==2.5.0
@@ -185,9 +201,9 @@ prometheus-client==0.19.0
python-dotenv==1.0.0 python-dotenv==1.0.0
pytest==7.4.3 pytest==7.4.3
httpx==0.25.1 httpx==0.25.1
```
#3.2 Fichier : `src\app\main.py `(CORRIGÉ) #3.2 Fichier : src\app\main.py (CORRIGÉ)
```
from fastapi import FastAPI, Request, Response, HTTPException from fastapi import FastAPI, Request, Response, HTTPException
from prometheus_client import Counter, Histogram, generate_latest, CONTENT_TYPE_LATEST from prometheus_client import Counter, Histogram, generate_latest, CONTENT_TYPE_LATEST
import time import time
@@ -403,7 +419,12 @@ USER devopsuser
# Commande de démarrage # Commande de démarrage
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--no-access-log"] CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--no-access-log"]
```
#🐳 ÉTAPE 4 : DOCKER COMPOSE CORRIGÉ
#4.1 Fichier : docker\docker-compose.yml (RECOMMENCÉ)
## 🐳 ÉTAPE 4 : DOCKER COMPOSE CORRIGÉ ## 🐳 ÉTAPE 4 : DOCKER COMPOSE CORRIGÉ
### 4.1 Fichier : `docker\docker-compose.yml` (RECOMMENCÉ) ### 4.1 Fichier : `docker\docker-compose.yml` (RECOMMENCÉ)
@@ -527,6 +548,7 @@ volumes:
name: portainer-data name: portainer-data
app-logs: app-logs:
name: app-logs name: app-logs
#4.2 Fichier : docker\prometheus.yml (À CRÉER) #4.2 Fichier : docker\prometheus.yml (À CRÉER)
global: global:
@@ -570,7 +592,8 @@ scrape_configs:
# alertmanagers: # alertmanagers:
# - static_configs: # - static_configs:
# - targets: [] # - targets: []
```
#4.3 Exécution Docker Compose :
## 4.3 Exécution Docker Compose : ## 4.3 Exécution Docker Compose :
@@ -597,10 +620,11 @@ curl http://localhost:8000
ou dans PowerShell ou dans PowerShell
``` ```
Invoke-WebRequest -Uri "http://localhost:8000" -UseBasicParsing Invoke-WebRequest -Uri "http://localhost:8000" -UseBasicParsing
```
##☸️ ÉTAPE 5 : KUBERNETES SIMPLIFIÉ POUR WINDOWS
### 5.1 Activer Kubernetes dans Docker Desktop : #☸️ ÉTAPE 5 : KUBERNETES SIMPLIFIÉ POUR WINDOWS
#5.1 Activer Kubernetes dans Docker Desktop :
1. Docker Desktop → Settings (roue crantée) 1. Docker Desktop → Settings (roue crantée)
2. Onglet Kubernetes 2. Onglet Kubernetes
@@ -608,6 +632,8 @@ Invoke-WebRequest -Uri "http://localhost:8000" -UseBasicParsing
4. ✅ Show system containers (optional) 4. ✅ Show system containers (optional)
5. Apply & Restart (patienter 2-3 minutes) 5. Apply & Restart (patienter 2-3 minutes)
#5.2 Vérification :
### 5.2 Vérification : ### 5.2 Vérification :
Vérifier que Kubernetes fonctionne Vérifier que Kubernetes fonctionne
@@ -618,7 +644,8 @@ kubectl get nodes
# Doit afficher : docker-desktop Ready # Doit afficher : docker-desktop Ready
kubectl get pods --all-namespaces kubectl get pods --all-namespaces
# Doit montrer les pods système # Doit montrer les pods système
```
#5.3 Fichier : kubernetes\manifests\namespace.yaml
#### 5.3 Fichier : kubernetes\manifests\namespace.yaml #### 5.3 Fichier : kubernetes\manifests\namespace.yaml
``` ```
@@ -629,7 +656,8 @@ metadata:
labels: labels:
name: devops-demo name: devops-demo
environment: development environment: development
```
#5.4 Fichier : kubernetes\manifests\configmap.yaml (NOUVEAU)
### 5.4 Fichier : kubernetes\manifests\configmap.yaml (NOUVEAU) ### 5.4 Fichier : kubernetes\manifests\configmap.yaml (NOUVEAU)
``` ```
@@ -643,7 +671,8 @@ data:
APP_NAME: "devops-windows-app" APP_NAME: "devops-windows-app"
LOG_LEVEL: "INFO" LOG_LEVEL: "INFO"
PYTHONUNBUFFERED: "1" PYTHONUNBUFFERED: "1"
```
#5.5 Fichier : kubernetes\manifests\deployment.yaml (SIMPLIFIÉ)
### 5.5 Fichier : kubernetes\manifests\deployment.yaml (SIMPLIFIÉ) ### 5.5 Fichier : kubernetes\manifests\deployment.yaml (SIMPLIFIÉ)
``` ```
@@ -718,7 +747,6 @@ spec:
protocol: TCP protocol: TCP
name: http name: http
type: NodePort # CORRIGÉ : NodePort au lieu de LoadBalancer pour Windows type: NodePort # CORRIGÉ : NodePort au lieu de LoadBalancer pour Windows
```
#5.6 Déploiement Kubernetes : #5.6 Déploiement Kubernetes :
@@ -743,7 +771,10 @@ kubectl get svc -n devops-demo devops-app-service -o jsonpath='{.spec.ports[0].n
# 5. Accéder à l'application # 5. Accéder à l'application
# http://localhost:[PORT] (ex: http://localhost:30456) # http://localhost:[PORT] (ex: http://localhost:30456)
#🏗️ ÉTAPE 6 : TERRAFORM SIMPLIFIÉ (OPTIONNEL) #🏗️ ÉTAPE 6 : TERRAFORM SIMPLIFIÉ (OPTIONNEL)
#⚠️ IMPORTANT : Terraform + Docker sur Windows/WSL2 est complexe. #⚠️ IMPORTANT : Terraform + Docker sur Windows/WSL2 est complexe.
#Je recommande de SAUTER cette étape pour les débutants. #Je recommande de SAUTER cette étape pour les débutants.
Si vous voulez quand même essayer : Si vous voulez quand même essayer :
@@ -863,6 +894,7 @@ output "application_url" {
output "namespace" { output "namespace" {
value = kubernetes_namespace.devops.metadata[0].name value = kubernetes_namespace.devops.metadata[0].name
} }
#6.2 Utilisation Terraform : #6.2 Utilisation Terraform :
cd C:\DevOpsProject\terraform cd C:\DevOpsProject\terraform
@@ -878,7 +910,10 @@ terraform apply
# Pour détruire # Pour détruire
terraform destroy terraform destroy
#📦 ÉTAPE 7 : HELM SIMPLE POUR WINDOWS #📦 ÉTAPE 7 : HELM SIMPLE POUR WINDOWS
#7.1 Création d'un chart Helm simple : #7.1 Création d'un chart Helm simple :
cd C:\DevOpsProject\kubernetes\helm cd C:\DevOpsProject\kubernetes\helm
@@ -935,6 +970,7 @@ app:
monitoring: monitoring:
enabled: true enabled: true
prometheusScrape: true prometheusScrape: true
#7.4 Fichier : kubernetes\helm\devops-chart\templates\deployment.yaml #7.4 Fichier : kubernetes\helm\devops-chart\templates\deployment.yaml
apiVersion: apps/v1 apiVersion: apps/v1
@@ -981,6 +1017,7 @@ spec:
port: {{ .Values.app.service.targetPort }} port: {{ .Values.app.service.targetPort }}
initialDelaySeconds: 10 initialDelaySeconds: 10
periodSeconds: 15 periodSeconds: 15
#7.5 Installation avec Helm : #7.5 Installation avec Helm :
cd C:\DevOpsProject\kubernetes\helm cd C:\DevOpsProject\kubernetes\helm
@@ -996,7 +1033,10 @@ helm upgrade devops-release ./devops-chart -n devops-demo
# Désinstaller # Désinstaller
helm uninstall devops-release -n devops-demo helm uninstall devops-release -n devops-demo
#🔄 ÉTAPE 8 : GITHUB ACTIONS CORRIGÉ #🔄 ÉTAPE 8 : GITHUB ACTIONS CORRIGÉ
#8.1 Fichier : .github\workflows\ci-cd.yml (PRATIQUE) #8.1 Fichier : .github\workflows\ci-cd.yml (PRATIQUE)
name: CI/CD DevOps Windows name: CI/CD DevOps Windows
@@ -1095,7 +1135,10 @@ jobs:
echo "kubectl apply -f kubernetes/manifests/" echo "kubectl apply -f kubernetes/manifests/"
echo "ou" echo "ou"
echo "helm upgrade --install ..." echo "helm upgrade --install ..."
#📊 ÉTAPE 9 : MONITORING FONCTIONNEL #📊 ÉTAPE 9 : MONITORING FONCTIONNEL
#9.1 Dashboard Grafana prêt à l'emploi : #9.1 Dashboard Grafana prêt à l'emploi :
# Créer un dossier pour les dashboards Grafana # Créer un dossier pour les dashboards Grafana
@@ -1127,6 +1170,7 @@ mkdir C:\DevOpsProject\docker\grafana-dashboards
} }
} }
'@ | Out-File -FilePath "C:\DevOpsProject\docker\grafana-dashboards\dashboard.json" -Encoding UTF8 '@ | Out-File -FilePath "C:\DevOpsProject\docker\grafana-dashboards\dashboard.json" -Encoding UTF8
#9.2 Accès aux interfaces : #9.2 Accès aux interfaces :
✅ Après docker-compose up -d : ✅ Après docker-compose up -d :
@@ -1142,7 +1186,10 @@ mkdir C:\DevOpsProject\docker\grafana-dashboards
1. Application K8s : http://localhost:[NODE_PORT] 1. Application K8s : http://localhost:[NODE_PORT]
(trouvez le port avec : kubectl get svc -n devops-demo) (trouvez le port avec : kubectl get svc -n devops-demo)
#🛠️ ÉTAPE 10 : SCRIPTS PRATIQUES #🛠️ ÉTAPE 10 : SCRIPTS PRATIQUES
#10.1 Script : scripts\setup.ps1 (AMÉLIORÉ) #10.1 Script : scripts\setup.ps1 (AMÉLIORÉ)
# DevOps Windows Setup Script # DevOps Windows Setup Script
@@ -1411,7 +1458,10 @@ Write-Host "✅ Toutes les ressources ont été nettoyées" -ForegroundColor Gre
Write-Host "" Write-Host ""
Write-Host "Pour recommencer :" -ForegroundColor Cyan Write-Host "Pour recommencer :" -ForegroundColor Cyan
Write-Host " .\setup.ps1" -ForegroundColor Gray Write-Host " .\setup.ps1" -ForegroundColor Gray
#🎯 VALIDATION FINALE #🎯 VALIDATION FINALE
#Testez votre installation : #Testez votre installation :
# 1. Lancer le setup # 1. Lancer le setup
@@ -1469,7 +1519,7 @@ Votre stack DevOps Windows est maintenant fonctionnelle et prête à l'emploi !
# Commentaire de Oualim # Commentaire de Oualim
# Avant d'aller plus loin, les partie 6,7 et 8 n'étant pas encore abordée à cette étape, en lançant uniquement les commandes de la partie 4.3 on se retrouvera avec des containeurs orphelins : # Avant d'aller plus loin, les #6, #7 et #8 n'étant pas encore abordée à cette étape, en lançant uniquement les commandes de le #3 on se retrouvera avec des containeurs orphelins :
PS C:\DevOpsProject\docker> docker-compose ps PS C:\DevOpsProject\docker> docker-compose ps
"....Found orphan containers ([gitea logstash kibana filebeat elasticsearch devops-db])...." "....Found orphan containers ([gitea logstash kibana filebeat elasticsearch devops-db])...."

16
src/app/.dockerignore Normal file
View File

@@ -0,0 +1,16 @@
__pycache__
*.pyc
.pytest_cache
.coverage
.git
.gitignore
README.md
Dockerfile
.dockerignore
.env
*.log
node_modules
.vscode
.idea
tests/
docs/

View File

@@ -1,66 +1,32 @@
# ========================== # Phase de base
# STAGE 1 : Construction FROM python:3.11-slim AS base
# ==========================
FROM python:3.11-slim AS builder
WORKDIR /app WORKDIR /app
# Installer les dépendances système
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \ build-essential libpq-dev gcc libpq5 && rm -rf /var/lib/apt/lists/*
libpq-dev \
gcc \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*
# Créer un environnement virtuel RUN pip install --upgrade pip
COPY src/app/requirements.txt .
RUN python -m venv /venv RUN python -m venv /venv
ENV PATH="/venv/bin:$PATH" ENV PATH="/venv/bin:$PATH"
RUN /venv/bin/pip install --no-cache-dir -r requirements.txt
# Installer les dépendances # Phase finale
COPY src/app/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# ==========================
# STAGE 2 : Production
# ==========================
FROM python:3.11-slim AS runtime FROM python:3.11-slim AS runtime
# Définir le répertoire de travail WORKDIR /app # 🔴 Ajouté : définit le répertoire de travail
WORKDIR /app
# Installer les bibliothèques système COPY --from=base /venv /venv
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 \
&& rm -rf /var/lib/apt/lists/*
# 🔥 Installe curl ici
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
# Créer un utilisateur non-root
RUN useradd -m -u 1000 devopsuser
# Copier l'environnement virtuel
COPY --from=builder /venv /venv
ENV PATH="/venv/bin:$PATH" ENV PATH="/venv/bin:$PATH"
# Copier le code
COPY src/app /app COPY src/app /app
COPY TpDevOpsProject.md /app/TpDevOpsProject.md
# Changer les droits RUN useradd -m -u 1000 devopsuser && chown -R devopsuser:devopsuser /app
RUN chown -R devopsuser:devopsuser /app
USER devopsuser USER devopsuser
# Variables d'environnement
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV ENV=production
ENV HOSTNAME=devops-container
ENV PYTHONPATH="/app"
EXPOSE 8000 EXPOSE 8000
# Lancer l'application CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--app-dir", "/app"]
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--no-access-log"]

Binary file not shown.

View File

@@ -1,153 +1,79 @@
# ========================== import traceback
# IMPORTS DES DÉPENDANCES import os
# ========================== from pathlib import Path
from fastapi import FastAPI, Request, HTTPException, Response from fastapi import FastAPI, Request, HTTPException, Response
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
from prometheus_client import Counter, Histogram, generate_latest, CONTENT_TYPE_LATEST from prometheus_client import Counter, Histogram, generate_latest, CONTENT_TYPE_LATEST
import time import time
import os
import logging import logging
from typing import Dict import markdown
# Import du routeur pour /users
from routes import router as routes_app from routes import router as routes_app
# ==========================
# CONFIGURATION DE L'APPLICATION
# ==========================
# Configuration du logging
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Création de l'application FastAPI app = FastAPI(title="DevOps Windows API", description="Application de démonstration DevOps sous Windows", version="1.0.0")
app = FastAPI(
title="DevOps Windows API",
description="Application de démonstration DevOps sous Windows",
version="1.0.0"
)
# Inclusion du routeur (doit être après la création de 'app') # 🔹 Utilise un chemin absolu pour le dossier templates
app.include_router(routes_app, prefix="/users", tags=["users"]) BASE_DIR = Path(__file__).resolve().parent
templates = Jinja2Templates(directory=str(BASE_DIR / "templates"))
# ========================== app.include_router(routes_app, prefix="/users", tags=["users"])
# MÉTRIQUES PROMETHEUS
# ==========================
REQUEST_COUNT = Counter(
'http_requests_total',
'Total des requêtes HTTP',
['method', 'endpoint', 'status']
)
REQUEST_LATENCY = Histogram( REQUEST_COUNT = Counter('http_requests_total', 'Total des requêtes HTTP', ['method', 'endpoint', 'status'])
'http_request_duration_seconds', REQUEST_LATENCY = Histogram('http_request_duration_seconds', 'Temps de réponse HTTP', ['method', 'endpoint'])
'Temps de réponse HTTP',
['method', 'endpoint']
)
# ==========================
# MIDDLEWARE DE MONITORING
# ==========================
@app.middleware("http") @app.middleware("http")
async def monitor_requests(request: Request, call_next): async def monitor_requests(request: Request, call_next):
"""Middleware pour suivre les requêtes et mesurer la latence."""
start_time = time.time() start_time = time.time()
try: try:
response = await call_next(request) response = await call_next(request)
status_code = str(response.status_code) status_code = str(response.status_code)
except Exception as e: except Exception as e:
status_code = "500" status_code = "500"
response = Response( response = Response(content=f"Erreur serveur : {str(e)}", status_code=500)
content=f"Erreur serveur : {str(e)}",
status_code=500
)
process_time = time.time() - start_time process_time = time.time() - start_time
REQUEST_COUNT.labels(method=request.method, endpoint=request.url.path, status=status_code).inc()
# Enregistrement des métriques REQUEST_LATENCY.labels(method=request.method, endpoint=request.url.path).observe(process_time)
REQUEST_COUNT.labels(
method=request.method,
endpoint=request.url.path,
status=status_code
).inc()
REQUEST_LATENCY.labels(
method=request.method,
endpoint=request.url.path
).observe(process_time)
# Ajout du temps de traitement dans les headers
response.headers["X-Process-Time"] = f"{process_time:.3f}s" response.headers["X-Process-Time"] = f"{process_time:.3f}s"
return response return response
# ========================== @app.get("/", response_class=HTMLResponse)
# ENDPOINTS PRINCIPAUX async def home(request: Request):
# ========================== md_file_path = "/app/TpDevOpsProject.md"
try:
with open(md_file_path, "r", encoding="utf-8") as f:
md_content = f.read()
html_content = markdown.markdown(md_content)
except Exception as e:
html_content = f"<h3>Erreur de lecture du fichier :</h3><pre>{traceback.format_exc()}</pre>"
@app.get("/") header_banner = "🚀 <strong>$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ DevOps Stack Windows - Fonctionnel ! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$</strong>"
async def home():
"""Endpoint racine - Statut de l'application.""" try:
return { return templates.TemplateResponse("index.html", {
"message": "🚀 DevOps Stack Windows - Fonctionnel !", "request": request,
"environment": os.getenv("ENV", "development"), "header": header_banner,
"status": "running", "content": html_content
"hostname": os.getenv("HOSTNAME", "windows-devops"), })
"version": "1.0.0" except Exception as e:
} return HTMLResponse(f"<h3>Erreur de template :</h3><pre>{traceback.format_exc()}</pre>", status_code=500)
@app.get("/health") @app.get("/health")
async def health(): async def health(): return {"status": "healthy", "timestamp": time.time(), "service": "devops-app"}
"""Health check pour Kubernetes."""
return {
"status": "healthy",
"timestamp": time.time(),
"service": "devops-app"
}
@app.get("/metrics") @app.get("/metrics")
async def metrics(): async def metrics():
"""Endpoint pour Prometheus.""" try: return Response(content=generate_latest(), media_type=CONTENT_TYPE_LATEST)
try: except Exception as e: raise HTTPException(status_code=500, detail="Échec des métriques")
data = generate_latest()
return Response(
content=data,
media_type=CONTENT_TYPE_LATEST,
headers={"Cache-Control": "no-cache"}
)
except Exception as e:
logger.error(f"Erreur lors de la génération des métriques : {e}")
raise HTTPException(status_code=500, detail="Échec de la génération des métriques")
@app.get("/info") @app.get("/info")
async def info(): async def info(): return {
"""Informations système.""" "python_version": "3.11", "platform": "windows", "service": "FastAPI DevOps",
return { "features": ["docker", "kubernetes", "monitoring", "ci-cd"]
"python_version": "3.11", }
"platform": "windows",
"service": "FastAPI DevOps",
"features": ["docker", "kubernetes", "monitoring", "ci-cd"]
}
@app.get("/env") @app.get("/env")
async def show_env(): async def show_env(): return {"ENV": os.getenv("ENV", "not-set"), "HOSTNAME": os.getenv("HOSTNAME", "not-set")}
"""Affiche les variables d'environnement (sécurisées)."""
safe_env = {
"ENV": os.getenv("ENV", "not-set"),
"HOSTNAME": os.getenv("HOSTNAME", "not-set"),
"PYTHON_VERSION": os.getenv("PYTHON_VERSION", "not-set")
}
return safe_env
# ==========================
# LANCEMENT EN DÉVELOPPEMENT
# ==========================
if __name__ == "__main__":
import uvicorn
logger.info("Démarrage du serveur FastAPI...")
uvicorn.run(
app,
host="0.0.0.0",
port=8000,
log_level="info",
reload=True # Auto-reload en dev
)

View File

@@ -5,4 +5,6 @@ prometheus-client==0.19.0
python-dotenv==1.0.0 python-dotenv==1.0.0
pytest==7.4.3 pytest==7.4.3
httpx==0.25.1 httpx==0.25.1
psycopg2==2.9.9 psycopg2-binary==2.9.9
markdown==3.6
jinja2

View File

@@ -0,0 +1,9 @@
<!-- templates/index.html -->
<!DOCTYPE html>
<html>
<head><title>DevOps App</title></head>
<body>
<h1>{{ header|safe }}</h1>
<div>{{ content|safe }}</div>
</body>
</html>