Déploiement d’applications django simplifiées / PHP / CGI

de quoi s’agit-il

Je cherche une possibilité de simplifier le déploiement des applications django sur mon serveur. Actuellement, j’utilise une instance de uWSGI par application. Je ne veux pas gâcher les fichiers de configuration chaque fois que je télécharge un nouveau projet dans mon dossier www-root. Au lieu de cela, je recherche une solution similaire à PHP, où je peux télécharger un dossier de projet sur ma racine www et le rendre disponible via nginx-> uWSGI ou nginx-> Gunicorn “automatiquement” et sans avoir à modifier un fichier de configuration. Il serait également idéal de ne pas avoir de processus pour chaque application, afin de ne pas gaspiller de mémoire (car je n’utilise jamais plus d’une application à la fois) .

état actuel

Pour cela, j’ai trouvé que le mode empereur de uWSGI pour les applications django en combinaison avec des variables magiques peut fonctionner. Mais avec ma configuration, seuls les parameters d’une application django sont et restnt chargés, de sorte qu’aucun autre ne peut démarrer.

de uwsgi.conf.template :

 [uwsgi] master = true socket = :8000 master = true reuse-port = true reload-os-env = true vaccuum = true logto = /var/log/uwsgi-%n.log manage-script-name = true chdir = /usr/local/www/%n mount = /%n=%n/wsgi.py 

à partir de nginx.conf :

 location ~ ^/(.+)/(.+?)$ { include uwsgi_params; uwsgi_pass 10.0.0.106:8000; uwsgi_param UWSGI_SCRIPT $1.wsgi; uwsgi_param SCRIPT_NAME /$1; uwsgi_param UWSGI_CHDIR /usr/local/www/$1; uwsgi_param PATH_INFO "/$2"; # ssortingp path } location ~ ^/(.+)/$ { include uwsgi_params; uwsgi_pass 10.0.0.106:8000; uwsgi_param UWSGI_SCRIPT $1.wsgi; uwsgi_param SCRIPT_NAME $1; # uwsgi_param UWSGI_APPID /$1; uwsgi_param DJANGO_SETTINGS_MODULE $1.settings; uwsgi_param UWSGI_CHDIR /usr/local/www/$1; uwsgi_param PATH_INFO ''; } 

Après avoir bricolé un autre jour, je suis arrivé au point où j’ai une solution de travail. Ce ne sera pas la solution finale, mais cela fonctionne pour le moment et je vais essayer de mettre à jour cette réponse chaque fois que j’améliore encore cette configuration.

Configuration de base

C’est en quelque sorte proche de ce que l’on peut trouver dans la documentation . J’ai néanmoins trouvé difficile de le faire fonctionner de cette façon.

nginx.conf

 server { server_name test.example.com; listen [::]:80; location ~ ^/(.+)/static/(.+)$ { alias /usr/local/www/$1/static/$2; } location ~ ^/(.+)/media/(.+)$ { alias /usr/local/www/$1/media/$2; } location ~ ^/(.*?)/ { uwsgi_pass unix:///var/run/uwsgi/$1.sock; include uwsgi_params; } } 

/usr/local/www/uwsgi.skel

 [uwsgi] master = true socket = /var/run/uwsgi/%c.sock reuse-port = true master = true reload-os-env = true vaccuum = true logto = /var/log/uwsgi/%c.log manage-script-name = true chdir = /usr/local/www/%c touch-reload = /usr/local/www/%c/%c wsgi-file = %c/wsgi.py mount = /%c=%c/wsgi.py static-map = /static=/usr/local/www/%c/static static-map = /media=/usr/local/www/%c/media unenv = DJANGO_SETTINGS_MODULE unenv = DJANGO_SETTINGS wsgi-env-behaviour = holy print = we are using %c 

Nous devons créer les dossiers requirejs pour les fichiers de socket et de journal et prendre soin des permissions nécessaires (voir également ci-dessous). Notez également que /var/run/ peut ne pas survivre à un redémarrage de votre système d’exploitation, afin qu’un autre dossier soit mieux adapté:

 chmod -R www:www /usr/local/www mkdir /var/log/uwsgi/ chmod -R www:www /var/log/uwsgi/ mkdir /var/run/uwsgi/ chmod -R www:www /var/run/uwsgi/ 

Lancement de l’instance principale uWSGI …

Nous pouvons maintenant lancer le processus uwsgi en mode empereur, même en mode empereur-tyrant :

 uwsgi --emperor 'glob:///usr/local/www/*/uwsgi.ini' --emperor-nofollow --emperor-tyrant \ --master --thunder-lock --enable-threads 

Et voici une astuce que j’ai utilisée: Le glob essaiera d’aspirer un fichier appelé uwsgi.ini à partir de chaque répertoire sous /usr/local/www/ . Cela aurait pu être un fichier individuel, mais je viens de lier le fichier skel ci-dessus (ce qui répond à mes exigences pour ne pas avoir à éditer un fichier de configuration) :

 cd /usr/local/www/django-app1/ ln -s ../uwsgi.skel uwsgi.ini 

Cela est également pratique car les versions récentes de GIT prennent également en charge les liens symboliques, de sorte que le lien symbolique sur mon uwsgi.skel développement peut avoir d’autres valeurs dans le fichier uwsgi.skel (par exemple, pas /usr/local/www mais /var/www/ )

Un mot sur les permissions et le mode ’empereur-tyran’ …

Le mode empereur-tyrant fera apparaître les processus uWSGI appartenant à différents utilisateurs. Quel utilisateur dépend des permissions du fichier uwsgi.ini. Le processus uWSGI supprime alors ses privilèges et s’exécute sous le nom d’utilisateur auquel appartient le fichier. Je n’ai pas encore besoin de cette fonctionnalité, mais si vous essayez d’installer une plate-forme d’hébergement professionnelle, vous en aurez besoin. Pour cela, gardez à l’esprit que nginx doit disposer d’permissions suffisantes pour lire et écrire les fichiers de socket générés et que /var/run/uwsgi/ doit également être accessible en écriture pour tous ces utilisateurs.

Mise en place d’un environnement virtuel

Après environ un an sans un seul problème, j’ai trouvé un de mes sites dans un état non opérationnel. Il s’est avéré que cela était dû à une mise à jour se déplaçant vers python3. Pour faire court: je devais bricoler un peu, car la configuration d’un environnement virtuel pour l’un des sites n’était pas aussi sortingviale, car je n’obtenais No module named site erreur de No module named site après avoir ajouté virtualenv = à mon uwsgi.ini . Mon nouveau fichier ini ressemble maintenant à ceci:

/usr/local/www/project/uwsgi.ini

 [uwsgi] master = true socket = /var/run/uwsgi/%c.sock reuse-port = true reload-os-env = true vaccuum = true manage-script-name = true logto = /var/log/uwsgi/%c.log virtualenv = /usr/local/www/katalogpro/venv/ chdir = /usr/local/www/%c touch-reload = /usr/local/www/%c/%c mount = /%c=%c/wsgi.py static-map = /static=/usr/local/www/%c/static static-map = /media=/usr/local/www/%c/media print = we are using %c # set cheaper algorithm to use, if not set default will be used cheaper-algo = backlog cheaper-overload = 4 cheaper-idle = 1 cheaper-initial = 0 

Notez que cela est devenu un peu plus facile, car il y a moins de parameters. Il est peut-être possible de peaufiner cela et d’utiliser la configuration en tant que .skel -configuration avec une instruction if, qui ajoute automatiquement virtualenv s’il y en a une. Pour l’instant, ça marche à nouveau et je suis heureux.