Cette procédure décrit un déploiement production avec :
- un conteneur Python 3.12 Django/Gunicorn ;
- un conteneur MariaDB ;
- Apache sur l'hôte comme reverse proxy ;
hypervisor.yamletconfig.yamlstockés hors image Docker ;- une persistance MariaDB via volume Docker ;
- une persistance des fichiers statiques collectés via volume Docker.
Internet / LAN
|
Apache host
|
| reverse proxy http://127.0.0.1:8000
|
Docker Compose
|
+-- web: Python 3.12 + Django + Gunicorn
| |
| +-- volume static-data -> /app/staticfiles
| +-- bind mount ./hypervisor.yaml -> /app/hypervisor.yaml:ro
| +-- bind mount ./config.yaml -> /app/config.yaml:ro
|
+-- db: MariaDB
|
+-- volume mariadb-data
Les fichiers suivants doivent exister sur le serveur, dans le dossier du projet, mais ne sont pas inclus dans l'image Docker :
.envhypervisor.yamlconfig.yaml
Ils sont exclus par .dockerignore et .gitignore.
Dans docker-compose.yml, hypervisor.yaml et config.yaml sont montés en lecture seule dans le conteneur web :
volumes:
- ./hypervisor.yaml:/app/hypervisor.yaml:ro
- ./config.yaml:/app/config.yaml:roCréer .env depuis .env.sample :
cp .env.sample .envPuis modifier au minimum :
DJANGO_SECRET_KEYDJANGO_ALLOWED_HOSTSDJANGO_CSRF_TRUSTED_ORIGINSWHEREISMYVM_DB_PASSWORDMARIADB_ROOT_PASSWORD
Exemple :
DJANGO_DEBUG=False
DJANGO_SECRET_KEY=une-cle-longue-et-aleatoire
DJANGO_ALLOWED_HOSTS=whereismyvm.example.com,127.0.0.1,localhost
DJANGO_CSRF_TRUSTED_ORIGINS=https://whereismyvm.example.com
DJANGO_USE_X_FORWARDED_PROTO=True
DJANGO_SESSION_COOKIE_SECURE=True
DJANGO_CSRF_COOKIE_SECURE=True
WHEREISMYVM_DB_ENGINE=mariadb
WHEREISMYVM_DB_NAME=whereismyvm
WHEREISMYVM_DB_USER=whereismyvm
WHEREISMYVM_DB_PASSWORD=mot-de-passe-app
WHEREISMYVM_DB_HOST=db
WHEREISMYVM_DB_PORT=3306
MARIADB_ROOT_PASSWORD=mot-de-passe-root-mariadbLa base MariaDB est persistée dans le volume Docker nommé mariadb-data.
Dans docker-compose.yml :
volumes:
mariadb-data:Ce volume est monté dans le conteneur MariaDB sur :
/var/lib/mysql
Cela signifie que les données survivent aux redémarrages et recréations de conteneurs.
Attention : supprimer le volume supprime la base.
docker compose down
docker volume rm vmwarewebutils_branche_dev_mariadb-dataLe nom exact du volume peut varier selon le nom du dossier ou le nom de projet Docker Compose.
Les fichiers statiques collectés par Django sont stockés dans le volume Docker nommé static-data.
Dans docker-compose.yml :
volumes:
static-data:Ce volume est monté dans le conteneur web sur :
/app/staticfiles
Le conteneur web exécute collectstatic automatiquement au démarrage si RUN_COLLECTSTATIC=1.
Gunicorn/Django sert l'application derrière Apache, et les fichiers statiques sont servis par WhiteNoise depuis /app/staticfiles.
Apache peut donc proxyfier toute l'application vers http://127.0.0.1:8000/ sans configuration Alias /static/ séparée.
Si Apache doit servir les fichiers statiques directement plus tard, il faudra remplacer le volume nommé static-data par un bind mount lisible par l'hôte, ou synchroniser /app/staticfiles vers un chemin lisible par Apache.
L'image applicative est construite depuis python:3.12-slim.
Construire et démarrer :
docker compose up -d --buildVoir les logs :
docker compose logs -f web
docker compose logs -f dbAppliquer les migrations est fait automatiquement au démarrage du conteneur web si RUN_MIGRATIONS=1.
Collecter les fichiers statiques est fait automatiquement si RUN_COLLECTSTATIC=1.
docker compose exec web python manage.py createsuperuserLe conteneur web expose Gunicorn sur l'hôte uniquement en local :
ports:
- "127.0.0.1:8000:8000"Apache peut donc proxyfier vers http://127.0.0.1:8000/.
Exemple HTTP :
<VirtualHost *:80>
ServerName whereismyvm.example.com
ServerAdmin admin@example.com
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8000/
ProxyPassReverse / http://127.0.0.1:8000/
ErrorLog /var/log/httpd/whereismyvm_error.log
CustomLog /var/log/httpd/whereismyvm_access.log combined
</VirtualHost>Exemple HTTPS :
<VirtualHost *:443>
ServerName whereismyvm.example.com
ServerAdmin admin@example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/whereismyvm.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/whereismyvm.example.com/privkey.pem
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8000/
ProxyPassReverse / http://127.0.0.1:8000/
RequestHeader set X-Forwarded-Proto "https"
ErrorLog /var/log/httpd/whereismyvm_ssl_error.log
CustomLog /var/log/httpd/whereismyvm_ssl_access.log combined
</VirtualHost>Modules Apache habituellement nécessaires :
a2enmod proxy proxy_http headers sslSur RHEL/CentOS/Rocky avec httpd, les modules sont souvent disponibles via la configuration Apache existante.
Sauvegarde logique MariaDB manuelle :
docker compose exec db mariadb-dump -u root -p whereismyvm > whereismyvm_backup.sqlPour automatiser une sauvegarde quotidienne avec rétention, utiliser le script fourni :
bash scripts/backup_mariadb.shLa profondeur de rétention se configure au début du script :
BACKUP_RETENTION_DAYS=30Par défaut, les fichiers de backup sont écrits dans backups/mariadb/ et sont ignorés par Git.
Exemple de cron pour une sauvegarde quotidienne à 03:00 :
0 3 * * * cd /opt/whereismyvm && bash scripts/backup_mariadb.sh >> /var/log/whereismyvm-db-backup.log 2>&1Restauration :
docker compose exec -T db mariadb -u root -p whereismyvm < whereismyvm_backup.sqlSauvegarder aussi :
.envhypervisor.yamlconfig.yaml
git pull
docker compose up -d --buildLe conteneur web relancera les migrations au démarrage si RUN_MIGRATIONS=1.
WhereIsMyVM fournit une commande Django dédiée au refresh d'inventaire :
python manage.py refresh_inventoryDans le déploiement Docker Compose, elle s'exécute depuis le conteneur web :
cd /opt/whereismyvm
docker compose exec -T web python manage.py refresh_inventoryExemple de crontab pour un refresh quotidien à 02:00 :
0 2 * * * cd /opt/whereismyvm && docker compose exec -T web python manage.py refresh_inventory >> /var/log/whereismyvm-refresh.log 2>&1Exemple de crontab pour un refresh hebdomadaire le dimanche à 02:00 :
0 2 * * 0 cd /opt/whereismyvm && docker compose exec -T web python manage.py refresh_inventory >> /var/log/whereismyvm-refresh.log 2>&1Pour désactiver la planification, commenter ou supprimer la ligne correspondante dans la crontab.
Éditer la crontab de l'utilisateur courant :
crontab -eLister les tâches planifiées :
crontab -lLa progression visuelle de l'interface web concerne uniquement le refresh manuel. Un refresh lancé par cron écrit dans les logs cron et met à jour la base de données.
Le docker-compose.yml démarre Gunicorn avec un seul worker.
C'est volontaire : la barre de progression du refresh est stockée en mémoire dans le processus Django. Avec plusieurs workers, le refresh pourrait être lancé dans un worker et le polling de progression arriver dans un autre worker qui ne connaît pas l'état du refresh.
Plusieurs workers sont intéressants quand :
- l'application reçoit beaucoup d'utilisateurs simultanés ;
- les requêtes sont nombreuses et indépendantes ;
- le serveur dispose de plusieurs coeurs CPU ;
- l'état partagé entre requêtes est stocké dans une base, Redis ou un autre stockage commun.
Pour WhereIsMyVM, garder un seul worker est préférable tant que la progression reste en mémoire.
Partager les sources sur GitHub ne change pas ce point. Le nombre de workers dépend du mode d'exécution en production, pas du fait que le code soit public.
Si un jour plusieurs workers deviennent nécessaires, il faudra d'abord déplacer l'état de progression vers un stockage partagé, par exemple MariaDB ou Redis.