Déploiement : Django - HE-Arc/slides-devweb GitHub Wiki

Prérequis

  1. Clés publiques des membres du projet ajoutées sur Github
  2. Container créé
  3. Mail d'information reçu contenant : votre port, URL, etc.
  4. Au minimum le projet par défaut de Django et de Vue.js fonctionnels

Infos du container

  • Image Docker : Ubuntu 22.04.3 LTS
  • Nginx : 1.18.0
  • Gunicorn : 21.2.0
  • Python : 3.10.12
  • pip : 22.0.2
  • Node.js : 20.11.0
  • NPM : 10.2.4

Connexion ssh au container

Connectez-vous en ssh sur le port communiqué par email et avec l'utilisateur django en utilisant la clé que vous avez ajoutée sur GitHub.

Avant de vous connecter, vérifiez que votre clé ssh soit ajoutée dans votre agent ssh local.

ssh [email protected] -p<PORT>

Particularités de vos containers

Dossier sauvegardé

Tout se qui se trouve dans le dossier /home/django/project/ seront sauvegardés. Nous avons donc mis en place des liens symboliques entre plusieurs fichiers de configuration placés à divers endroits sur votre container. Vous pourrez travailler uniquement dans le dossier project, afin de permettre d'éviter tout problème avec vos configurations en cas de redémarrage de votre container, plus de détails vous seront donnés dans la suite de cette documentation.

En cas de modification / recréation du container, seul le contenu de ce dossier "project" sera restauré veillez à garder les éléments importants dans ce dossier.

Automatisation

En cas de redémarrage de votre container, tout est supprimé et remis à zéro, sauf votre dossier "project".

Dans certains cas vous pourriez avoir besoin d'installer des bibliothèques, avoir besoin de mettre en place un CICD, avoir besoin de démarrer certaines commandes pour automatiser une partie ou tout votre déploiement, etc.

Afin de vous permettre de mettre ces choses en place, sans les perdre en cas de redémarrage et remise à zéro de votre container, nous vous avons mis en place un fichier nommé custom-start.sh placé dans le dossier sauvegardé "project". Ce fichier est un script qui est exécuté automatiquement à chaque redémarrage de votre container.

Exemple 1: si vous souhaitez installer automatiquement les dépendances de votre projet Django, vous pourriez imaginer de le faire via ce script.

Exemple 2 : si vous souhaitez mettre en place un CICD, vous pourriez scripter les étapes de configuration afin de les automatiser.

Vous n'êtes évidemment pas obligé de faire cela, mais dans le cas d'un crash ou redémarrage incontrôlé ou contrôlé de votre container, vous serez responsable de réaliser à nouveau toutes les étapes de configuration que vous avez réalisées la première fois.

Tests

Afin de tester si votre script de redémarrage fonctionne correctement il faut faire redémarrer votre container, afin d'éviter que vous deviez venir nous demander de le faire toutes les 5min, vous pouvez simplement effectuer les étapes suivantes :

  1. Récupérer le PID du service tail en exécutant la commande top par exemple
  2. Exécuter la commande sudo kill <PID>, où peut être remplacé par le PID du service tail

Suite à cette commande, le container va "crash". Notre système Kubernetes prendra ensuite le relais en détectant automatiquement le "crash" et redémarrera votre container. Ce processus ne devrait pas prendre plus de quelques secondes, soyez un petit peu patient ;) Si vous n'avez toujours pas accès à votre container après 5min environ, c'est qu'il y a un autre problème, n'hésitez pas à nous contacter.

Logs

Il existe également un fichier nommé custom-start.log qui stocke toutes les erreurs provoquées par votre script en cas de problème au démarrage du container. Cela vous sera utile en cas de redémarrage pour savoir si votre script à eu des soucis et lesquels, pas besoin donc de toucher à ce fichier, il est géré par le container lui-même.

--> INFORMATION IMPORTANTE <--

Actuellement nous avons un problème lors des redémarrages des containers, le service gunicorn ne redémarre pas. En attendant de trouver une solution pérenne, nous vous demandons d'ajouter la chose suivante en première ligne de votre script custom-start.sh :
sudo systemctl restart gunicorn

Vous pouvez à la suite de cette ligne écrire vos commandes sans problèmes.

Ceci aura pour effet de redémarrer le service gunicorn automatiquement, plus d'information pour récupérer le statut, stopper le service, le redémarrer, etc. plus bas dans la documentation.

Récupération de votre projet

Vous pouvez cloner votre projet sur le serveur de déploiement dans le dossier /home/django/project/. Utilisez idéalement SSH avec une clé de déploiement.

Source pour générer et utiliser des clés de déploiement : https://docs.github.com/en/developers/overview/managing-deploy-keys#deploy-keys

Installation des dépendances

Installer les dépendances des projets Django et Vue.js.

Vue.js

Pour Vue.js il suffit d'utiliser la commande npm install.

Django

Pour Django il y a plusieurs techniques, nous utiliserons celle qui consiste à créer un fichier requirements.txt et à utiliser ce fichier pour installer les dépendances.

Dans votre environnement de dév, déplacez-vous dans le dossier de votre projet Django et exécutez la commande pipenv requirements > requirements.txt. Cela aura pour effet de créer un fichier requirements.txt que vous pourrez utiliser sur le serveur de production. Vous pouvez push ce fichier sur git et le mettre à jour avant de déployer.

Dirigez-vous sur le serveur de production et récupérez les modifications afin d'obtenir le fichier requirements.txt. Rendez-vous ensuite à l'endroit où se trouve ce fichier et exécutez la commande pip install -r requirements.txt.

Vous pouvez également installer pipenv et utiliser pipenv sur le serveur à la place, mais je vous préviens la configuration n'est pas de tout repos ^^ Je vous recommande donc la technique expliquée au-dessus. Vous avez le choix ;)

Nginx

*/!\ IMPORTANT /!* Ce chapitre de la documentation a été mis à jour le 31.01.2023 avec une configuration Nginx plus flexible pour répondre à certains de cas de figure.

Avant le back et le front n'étaient pas dans le même sous-domaine, ce qui pose des problèmes pour certains systèmes, comme l'authentification avec cookies de sessions et d'autres systèmes.

Si vous utilisez un système nécessitant d'être sur le même sous-domaine, vous pouvez simplement continuer la lecture.

Si vous avez déjà tout mis en place et ne souhaitez pas mettre à jour votre configuration Nginx, vous trouverez un backup de ce chapitre de la documentation ici : https://github.com/HE-Arc/slides-devweb/wiki/D%C3%A9ploiement-:-Django-%5BOLD%5D

Si vous n'êtes pas sûr si vous avez besoin de ces modifications maintenant ou plus tard, je vous conseille de les appliquer, cela ne fera pas de mal. Cette configuration est simplement plus flexible, mais l'application de cette nouvelle configuration pourrait vous demander d'adapter un peu votre projet. Venez vers moi en cas de problèmes ou de questions.

Ces modifications changent les URLs de votre back et de votre front !

  • frontend : https://<PROJECT>.k8s.ing.he-arc.ch
  • backend : https://api-<PROJECT>.k8s.ing.he-arc.ch

Nginx est utilisé comme serveur web sur le container. La configuration que vous devez modifier se trouve dans /home/django/project/nginx.conf.

La config de Nginx se trouve en réalité dans /etc/nginx/sites-enabled/default, nous avons modifié légèrement le serveur afin d'en créer un lien symbolique pour vous faciliter la tâche et éviter des problèmes de sauvegarde en cas de soucis avec le serveur.

Configuration par défaut :

# Django
server {
    listen 80;
    server_name _;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /static/ {
        alias /home/django/.project-default/backend/static/;
    }
}

# Vuejs
server {
    listen 81;
    server_name  _;
    root   /home/django/.project-default/frontend/dist;
    location / {
        index  index.html;
        try_files $uri $uri/ index.html /index.html;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Dans votre projet vous avez un frontend et un backend, il faut donc avoir une configuration pour chaque partie. Dans ce chapitre nous allons devoir l'adapter pour que le frontend puisse fonctionner, la configuration du backend est déjà correcte pour Nginx.

Vous devez donc ici adapter la configuration de Nginx afin de la faire pointer sur le dossier dist.
Le dossier dist peut être généré en exécutant npm run build.

Si vous changez la configuration Nginx, vous devrez redémarrer Nginx avec sudo service nginx restart.

Test

A ce stade, votre frontend devrait fonctionner.

L'url de votre application frontend est la suivante : https://<PROJECT>.k8s.ing.he-arc.ch

Gunicorn

Gunicorn est utilisé comme serveur WSGI sur le container. La configuration que vous devez modifier se trouve dans /home/django/project/gunicorn.conf.

La config de Nginx se trouve en réalité dans /etc/systemd/system/gunicorn.service, nous avons modifié légèrement le serveur afin d'en créer un lien symbolique pour vous faciliter la tâche et éviter des problèmes de sauvegarde en cas de soucis avec le serveur.

Configuration par défaut :

[Unit]
Description=GUnicorn wsgi service

[Service]
User=django
Group=www-data
WorkingDirectory=/home/django/.project-default/backend
ExecStart=/bin/sh -c "/usr/local/bin/gunicorn -w 3 --error-logfile /home/django/project/gunicorn-logs.log project.wsgi"
Restart=always

[Install]
WantedBy=multi-user.target

⚠️ REMARQUE ! --error-logfile ... est nécessaire, car sinon les erreurs sont redirigés par défaut sur STDERR, et comme gunicorn tourne dans un process elles vont dans le vide absolu...

Pour pouvoir déployer une app Python, Django dans notre cas, nous avons besoin d'un serveur WSGI (qui comprend le langage Python) et d'un serveur web (qui s'occupe de la communication entre client et serveur WSGI). Dans notre cas Gunicorn joue le rôle du serveur WSGI et Nginx le rôle du serveur web.

Vous devez donc ici adapter la configuration de Gunicorn de la manière suivante :

  • Modifier WorkingDirectory en faisant pointer le chemin sur le dossier de votre projet Django qui contient le fichier manage.py
  • Modifier ExecStart en remplaçant project par le nom du dossier contenant le fichier settings.py

Se référer à la documentation de Django pour le déploiement d'une application (https://docs.djangoproject.com/en/5.0/howto/deployment/#how-to-deploy-django)

Si vous changez la configuration Gunicorn, vous devrez redémarrer Gunicorn avec sudo systemctl restart gunicorn.

sudo systemctl status gunicorn peu vous aider à comprendre ce qu'il se passe en cas de problème. Ne pas oublier de regarder les logs aussi !!!

Si vous avez l'impression que le restart n'a pas d'effet, vous pouvez utiliser sudo systemctl stop gunicorn et vérifier que le processus a bien été supprimé avec top puis le restart.

Et si le stop n'a pas eu d'effet non plus, alors un petit kill <PID> et sudo systemctl restart gunicorn pourrait bien être utile ^^

Allowed hosts

Pour que votre serveur Django fonctionne en production, il faut au minimum modifier la variable ALLOWED_HOSTS dans le fichier settings.py et y mettre adresse de votre backend (ne pas mettre l'URL entière, juste l'adresse !) : <PROJECT>.k8s.ing.he-arc.ch

Test

A ce stade, votre backend devrait fonctionner.

L'url de votre application backend est la suivante : https://api-<PROJECT>.k8s.ing.he-arc.ch

Connexion à la base de données

Vous ne devez pas utiliser une base de données SQLite, mais bien une base de données PostgreSQL fournie.

Dans le dossier /root/config-mount et /root/secret-mount vous trouverez vos identifiants de connexion à la base de données. Notamment postgres-host, postgres-database, postgres-user, postgres-password et postgres-port. Ceux-ci sont uniquement accessibles en root (sudo su).

Vous devrez utiliser ces données dans le fichier settings.py de votre app Django afin qu'elle puisse se connecter à la base de données.

Suite de la configuration et communication entre backend et frontend

L'environnement de production/déploiement est très différent de celui de développement, ici je ne peux pas vous donner de marche à suivre étant donné que les configurations nécessaires dépendront de vos projets. Mais voici quelques pistes et éléments auxquels il faudra faire attention, à vous de compléter ces éléments en fonction de vos projets.

Vous allez devoir adapter passablement de choses supplémentaires pour que votre application fonctionne en production, comme toutes les URLs qui font référence à votre backend et votre frontend. Et vous devrez également faire attention à respecter les règles et les contraintes de déploiement des différents framework.

Afin d'éviter de devoir modifier les URLs partout dans votre projet à chaque déploiement, une bonne pratique est d'utiliser des fichiers .env autant en frontend qu'en backend. Ces fichiers ont l'avantage de pouvoir être configurés une seule fois (attention, il ne faut jamais push de fichier .env).

Fichiers static

Si vous avez besoin que Nginx serve vos fichiers static, il faudra mettre à jour l'alias de la configuration Nginx de /static/ avec le chemin correspondant à votre projet.

Comprenez d'abord se que sont les static files et si vous en avez besoin, avant de vous soucier de ce point.

Test final

A ce stade tout devrait fonctionner correctement.

L'url de votre application frontend est la suivante : https://<PROJECT>.k8s.ing.he-arc.ch L'url de votre application backend est la suivante : https://api-<PROJECT>.k8s.ing.he-arc.ch


Erreurs courantes

Afin d'avoir plus de détails sur l'état de votre déploiement vous pouvez exécuter la commande python3 manage.py check --deploy.

Pas d'erreurs apparentes / page blanches

Mettre le paramètre DEBUG dans le fichier settings.py à True pour que Django vous renvoie davantage de détails sur les erreurs.

IMPORTANT : Une fois votre déploiement réussi, remettez ce paramètre à False.

Documentations d'étudiants

Si vous avez écrit de la documentation à propos de votre déploiement, sur le wiki de votre projet ou ailleurs, vous pouvez indiquer le lien de cette dernière ci-dessous :

  • ...
⚠️ **GitHub.com Fallback** ⚠️