Skip to content

Latest commit

 

History

History
332 lines (228 loc) · 8.48 KB

File metadata and controls

332 lines (228 loc) · 8.48 KB

Déploiement Docker Compose

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.yaml et config.yaml stockés hors image Docker ;
  • une persistance MariaDB via volume Docker ;
  • une persistance des fichiers statiques collectés via volume Docker.

Architecture cible

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

Fichiers sensibles

Les fichiers suivants doivent exister sur le serveur, dans le dossier du projet, mais ne sont pas inclus dans l'image Docker :

  • .env
  • hypervisor.yaml
  • config.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:ro

Créer .env depuis .env.sample :

cp .env.sample .env

Puis modifier au minimum :

  • DJANGO_SECRET_KEY
  • DJANGO_ALLOWED_HOSTS
  • DJANGO_CSRF_TRUSTED_ORIGINS
  • WHEREISMYVM_DB_PASSWORD
  • MARIADB_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-mariadb

Persistance MariaDB

La 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-data

Le nom exact du volume peut varier selon le nom du dossier ou le nom de projet Docker Compose.

Fichiers statiques

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.

Démarrage

L'image applicative est construite depuis python:3.12-slim.

Construire et démarrer :

docker compose up -d --build

Voir les logs :

docker compose logs -f web
docker compose logs -f db

Appliquer 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.

Création du superuser

docker compose exec web python manage.py createsuperuser

Apache reverse proxy

Le 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 ssl

Sur RHEL/CentOS/Rocky avec httpd, les modules sont souvent disponibles via la configuration Apache existante.

Backups

Sauvegarde logique MariaDB manuelle :

docker compose exec db mariadb-dump -u root -p whereismyvm > whereismyvm_backup.sql

Pour automatiser une sauvegarde quotidienne avec rétention, utiliser le script fourni :

bash scripts/backup_mariadb.sh

La profondeur de rétention se configure au début du script :

BACKUP_RETENTION_DAYS=30

Par 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>&1

Restauration :

docker compose exec -T db mariadb -u root -p whereismyvm < whereismyvm_backup.sql

Sauvegarder aussi :

  • .env
  • hypervisor.yaml
  • config.yaml

Mise à jour applicative

git pull
docker compose up -d --build

Le conteneur web relancera les migrations au démarrage si RUN_MIGRATIONS=1.

Refresh planifié avec cron

WhereIsMyVM fournit une commande Django dédiée au refresh d'inventaire :

python manage.py refresh_inventory

Dans 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_inventory

Exemple 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>&1

Exemple 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>&1

Pour désactiver la planification, commenter ou supprimer la ligne correspondante dans la crontab.

Éditer la crontab de l'utilisateur courant :

crontab -e

Lister les tâches planifiées :

crontab -l

La 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.

Workers Gunicorn

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.