Comment déployer des applications Python WSGI en utilisant le serveur HTTP Gunicorn derrière Nginx
Introduction
C'était peut-être l'article sur la comparaison des serveurs Web Python qui vous a tenté de changer, ou bien le fait que vous avez tout simplement dépassé votre pile de déploiement d'application actuelle. Vous souhaitez en savoir plus sur le serveur Web Gunicorn et apprendre à déployer une application Python en profondeur depuis le début.
Dans cet article de DigitalOcean, notre objectif est de vous aider avec tout ce qui précède et même plus. Nous commencerons par approfondir notre connaissance de l'excellent serveur HTTP WSGI Gunicorn et continuerons avec le déploiement d'applications Web WSGI Python construites sur diverses frameworks populaires.
Glossaire
1. À propos de Gunicorn et Nginx
- Gunicorn
- Déploiement d'une application Web à l'aide de Nginx
2. Préparer votre Droplet pour la production
- Mise à jour du système d'exploitation par défaut
- Configuration de Python, pip et virtualenv
- Créer un environnement virtuel (Python)
- Téléchargement et installation de Gunicorn
- Télécharger et installer Nginx
3. Servir des applications Web Python avec Gunicorn
- WSGI
- Objet d'application WSGI (appelable) : wsgi.py
- Exécution du serveur
- Configurer et optimiser Gunicorn
- Configurer Nginx
- Conseils et suggestions divers
À propos de Gunicorn et Nginx
Gunicorn
Gunicorn est un serveur d'applications web WSGI autonome qui offre beaucoup de fonctionnalités. Il prend en charge nativement divers frameworks grâce à ses adaptateurs, ce qui en fait un remplacement extrêmement facile à utiliser pour de nombreux serveurs de développement utilisés pendant le développement.
Techniquement, le fonctionnement de Gunicorn est très similaire à celui du serveur web Unicorn, qui a connu du succès pour les applications Ruby. Tous deux utilisent ce qu'on appelle le modèle pré-fork. Cela, en essence, charge le processus maître central [Gunicorn] de gérer les travailleurs, la création de sockets et de liaisons, etc.
Points forts de Gunicorn Server
Exécute toute application web Python WSGI (et framework)
Peut être utilisé comme un remplacement direct pour Paster (Pyramid), le serveur de développement de Django, web2py, etc.
Vient avec divers types de travailleurs et configurations
Gère automatiquement les processus des travailleurs
Support de HTTP/1.0 et HTTP/1.1 (Keep-Alive) à travers des travailleurs synchrones et asynchrones
Prend en charge SSL
Extensible avec des hooks
Python 2.6+ et 3.x sont pris en charge
Déploiement d'une application Web à l'aide de Nginx
Nginx est un serveur web/proxy (inverse) très performant. Il a atteint sa popularité actuelle en raison de sa légèreté, de sa relative facilité d'utilisation et de sa simplicité d'extension (avec des modules complémentaires/plug-ins). Grâce à son architecture, il est capable de gérer beaucoup de requêtes (virtuellement illimitées), ce qui - en fonction de la charge de votre application ou de votre site web - pourrait être vraiment difficile à gérer avec d'autres alternatives plus anciennes.
Rappelez-vous : « Gérer » les connexions signifie techniquement ne pas les abandonner et être capable de les servir avec quelque chose. Vous devez toujours avoir votre application et votre base de données fonctionnant correctement afin que Nginx puisse servir aux clients des *réponses qui ne soient pas des messages d'erreur.
Pourquoi utiliser Nginx comme reverse-proxy devant un serveur d'application ?
De nombreux frameworks et serveurs d'applications (y compris Gunicorn) peuvent servir des fichiers statiques (par exemple, javascript, css, images, etc.) ainsi que des réponses. Cependant, il est préférable de laisser un serveur (proxy inverse) tel que Nginx gérer la tâche de servir ces fichiers et de gérer les connexions (demandes). Cela soulage une grande partie de la charge des serveurs d'applications, vous offrant une bien meilleure performance globale.
À mesure que votre application se développe, vous voudrez l'optimiser - et quand le moment viendra, la répartir sur des serveurs (VPS) afin de pouvoir gérer plus de connexions simultanément (et avoir une architecture généralement plus robuste). Avoir un reverse proxy devant vos serveurs d'application vous aide à cela dès le début.
L'extensibilité d'Nginx (par exemple, la mise en cache native ainsi que le basculement et d'autres mécanismes) est également un grand atout qui profite aux applications web contrairement aux serveurs d'applications (plus simples).
Exemple d'une architecture de serveur de base :
Client Request ----> Nginx (Reverse-Proxy)
|
/|\
| | `-> App. Server I. 127.0.0.1:8081
| `--> App. Server II. 127.0.0.1:8082
`----> App. Server III. 127.0.0.1:8083
Remarque : Veuillez consulter la section Configurer et optimiser Gunicorn pour apprendre combien de serveurs/travailleurs utiliser.
Préparer votre Droplet pour la production
Dans cette section, nous allons préparer notre environnement virtuel pour la production (c'est-à-dire pour déployer notre application).
Nous commencerons par :
mise à jour du système d'exploitation par défaut
télécharger et installer des outils Python courants (c'est-à-dire pip, virtualenv)
créer un environnement virtuel pour contenir l'application (à l'intérieur duquel se trouvent ses dépendances telles que Gunicorn)
Remarque : Les instructions données ici sont brèves. Pour en savoir plus, consultez notre article d'aide sur pip et virtualenv : Outils Python courants : Utiliser virtualenv, Installer avec Pip et Gérer les paquets.
Mise à jour du système d'exploitation par défaut
Remarque : Nous effectuerons les configurations et préparations suivantes sur un nouveau droplet, en utilisant des versions récentes des systèmes d'exploitation. En théorie, vous ne devriez pas rencontrer de problèmes en les testant sur votre VPS. Cependant, si vous l'utilisez déjà activement, nous vous recommandons fortement de passer à un nouveau système.
Pour nous assurer que nous avons les dernières versions disponibles des applications par défaut, nous devons mettre à jour notre système.
Pour les systèmes basés sur Debian (c'est-à-dire Ubuntu, Debian), exécutez ce qui suit :
aptitude update
aptitude -y upgrade
Pour les systèmes basés sur RHEL (c'est-à-dire CentOS), exécutez ce qui suit :
yum -y update
Configuration de Python, pip et virtualenv
Remarque pour les utilisateurs de CentOS/RHEL :
CentOS/RHEL, par défaut, arrive comme un serveur très léger. Son ensemble d'outils, qui est susceptible d'être obsolète pour vos besoins, n'est pas destiné à exécuter vos applications mais à alimenter les outils système du serveur (par exemple, YUM).
Pour préparer votre système CentOS, Python doit être configuré (c'est-à-dire compilé à partir des sources) et pip/virtualenv doivent être installés en utilisant cet interpréteur.
Pour en savoir plus sur Comment configurer Python 2.7.6 et 3.3.3 sur CentOS 6.4 et 5.8, avec pip et virtualenv, veuillez vous référer à : Comment configurer Python 2.7.6 et 3.3.3 sur CentOS.
Sur Ubuntu et Debian, une version récente de l'interpréteur Python que vous pouvez utiliser est fournie par défaut. Cela ne nous laisse qu'un nombre limité de packages supplémentaires à installer :
- python-dev (outils de développement),
- pip (pour gérer les paquets),
- virtualenv (pour créer des environnements virtuels isolés).
python-dev :
python-dev est un package au niveau du système d'exploitation qui contient des outils de développement étendus pour construire des modules Python.
Exécutez la commande suivante pour installer python-dev en utilisant aptitude :
aptitude install python-dev
pip :
pip est un gestionnaire de paquets qui nous aidera à installer les paquets d'application dont nous avons besoin.
Exécutez les commandes suivantes pour installer pip :
curl https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py | python -
curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python -
export PATH="/usr/local/bin:$PATH"
Vous pourriez avoir besoin de privilèges sudo.
virtualenv :
Il est préférable de contenir une application Python dans son propre environnement avec toutes ses dépendances. Un environnement peut être décrit de manière simple comme un emplacement isolé (un répertoire) où tout réside. Pour cela, un outil appelé virtualenv est utilisé.
Exécutez ce qui suit pour installer virtualenv en utilisant pip :
sudo pip install virtualenv
Créer un environnement virtuel autonome (Python)
Ayant tous les outils nécessaires prêts, nous pouvons créer un environnement pour déployer notre application.
Rappelle-toi : Si tu n'as pas de virtualenv sur ta machine de développement (locale) pour ton projet, tu devrais envisager d'en créer un et de déplacer ton application (ainsi que ses dépendances) à l'intérieur.
Commençons par créer un dossier qui contiendra à la fois l'environnement virtuel et votre module d'application :
Vous pouvez utiliser n'importe quel nom ici pour répondre à vos besoins.
mkdir my_app
Nous pouvons continuer en entrant dans ce dossier et en créant un nouvel environnement virtuel à l'intérieur.
Vous pouvez également choisir le nom que vous voulez pour votre environnement virtuel.
cd my_app
virtualenv my_app_venv
Créons un nouveau dossier là-bas pour contenir également votre module d'application Python :
Ceci est le dossier où votre module d'application résidera.
mkdir app
Et activez l'interpréteur à l'intérieur de l'environnement virtuel pour l'utiliser :
Veuillez vous assurer d'utiliser le nom que vous avez choisi pour votre environnement virtuel si vous avez opté pour autre chose que « my_app_venv ».
source my_app_venv/bin/activate
En fin de compte, c'est ainsi que votre répertoire principal de déploiement d'application devrait se présenter :
my_app # Main Folder to Contain Everything Together
|
|=== my_app_venv # V. Env. folder with the Python Int.
|=== app # Your application module
|..
|.
Téléchargement et installation de Gunicorn
Il est toujours recommandé de regrouper tous les éléments liés à l'application, autant que possible, à l'intérieur de l'environnement virtuel. Par conséquent, nous allons télécharger et installer Gunicorn là-bas.
Si vous ne travaillez pas dans un environnement, Gunicorn sera installé globalement (c'est-à-dire disponible système). Ce n'est pas recommandé. Optez toujours pour utiliser virtualenv.
Pour installer Gunicorn avec pip, exécutez ce qui suit :
pip install gunicorn
Télécharger et installer Nginx
Remarque pour les utilisateurs de CentOS/RHEL :
Les instructions ci-dessous ne fonctionneront pas sur les systèmes CentOS. Veuillez consulter les instructions ici pour CentOS.
Exécutez la commande suivante pour utiliser le gestionnaire de paquets par défaut du système aptitude pour installer Nginx :
sudo aptitude install nginx
Pour exécuter Nginx, vous pouvez utiliser ce qui suit :
sudo service nginx start
Pour arrêter Nginx, vous pouvez utiliser ce qui suit :
sudo service nginx stop
Pour redémarrer Nginx, vous pouvez utiliser ce qui suit :
Après chaque reconfiguration de Nginx, un redémarrage ou un rechargement est nécessaire pour que les nouveaux paramètres prennent effet.
sudo service nginx restart
Remarque : Pour en savoir plus sur Nginx sur Ubuntu, veuillez consulter notre article : Comment installer Nginx sur Ubuntu 12.04.
Servir des applications Web Python avec Gunicorn
Dans cette section, nous allons voir comment une application WSGI fonctionne avec Gunicorn. Ce processus consiste à fournir au serveur un appelable d'application WSGI (par exemple, application=(..)) comme point d'entrée.
WSGI
WSGI en un mot est une interface entre un serveur web et l'application elle-même. Elle existe pour assurer un moyen standardisé entre divers serveurs et applications (frameworks) afin de travailler ensemble, permettant une interopérabilité lorsque cela est nécessaire (par exemple, passer d'un environnement de développement à un environnement de production), ce qui est un besoin indispensable de nos jours.
Remarque : Si vous êtes intéressé à en savoir plus sur WSGI et les serveurs web Python, consultez notre article : Une comparaison des serveurs web pour les applications web basées sur Python.
Objet d'application WSGI (appelable) : wsgi.py
Comme mentionné ci-dessus, les serveurs web fonctionnant sur WSGI ont besoin d'un objet application (c'est-à-dire de votre application).
Avec la plupart des frameworks et des applications, cela consiste en :
- Un wsgi.py pour contenir et fournir un objet d'application (ou appelable) à être utilisé par le serveur.
Nous allons commencer par créer un fichier wsgi.py exemplaire à utiliser avec Gunicorn.
Vous pouvez choisir n'importe quel nom au lieu de « wsgi.py ». Cependant, ce sont ceux qui sont couramment utilisés (par exemple par Django).
Commençons par créer un fichier wsgi.py pour contenir une application WSGI de base.
Exécutez la commande suivante pour créer un wsgi.py à l'aide de l'éditeur de texte nano :
nano wsgi.py
Continuons avec le déplacement (copier/coller) du code de base de l'application WSGI à l'intérieur (qui devrait être remplacé par l'appelable de votre propre application pour la production) :
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return ["Hello!"]
Ceci est le fichier qui est inclus par le serveur et chaque fois qu'une requête arrive, le serveur utilise cette application callable pour exécuter les gestionnaires de requêtes de l'application (par exemple, les contrôleurs) lors de l'analyse de l'URL (par exemple, mysite.tld/controller/method/variable).
Après avoir placé le code de l'application, appuyez sur CTRL+X puis confirmez avec Y pour enregistrer ce fichier dans le dossier « my_app » aux côtés de l'environnement virtuel et du module d'application contenant votre application réelle.
Remarque : Cette application WSGI est l'exemple le plus basique de son genre. Vous devrez remplacer ce bloc de code par votre propre objet d'application provenant du module d'application.
Une fois que nous aurons terminé, voici à quoi devrait ressembler le répertoire de déploiement principal de votre application :
my_app # Main Folder to Contain Everything Together
|
|=== my_app_venv # V. Env. folder with the Python Int.
|=== app # Your application module
|
|--- wsgi.py # File containing application callable
|..
|.
Exécution du serveur
Pour commencer à servir votre application, vous devez simplement exécuter :
gunicorn [option] [option] .. [wsgi file]
Exécutez ce qui suit pour démarrer le serveur :
gunicorn -b 0.0.0.0:8080 wsgi
Cela fera fonctionner le serveur au premier plan. Si vous souhaitez l'arrêter, appuyez sur CTRL+C.
Pour exécuter le serveur en arrière-plan, exécutez ce qui suit :
gunicorn -b 0.0.0.0:8080 wsgi &
Lorsque vous exécutez une application en arrière-plan, vous devrez utiliser un gestionnaire de processus (par exemple htop) pour la tuer (ou l'arrêter).
Configurer et optimiser Gunicorn
Remarque : Ci-dessous se trouvent certains des paramètres de configuration et d'optimisation les plus couramment utilisés. Pour voir toutes les options disponibles, consultez la documentation officielle pour un aperçu de la configuration de Gunicorn.
Comme mentionné précédemment, Gunicorn est hautement configurable et il est très facile de modifier tous les paramètres nécessaires pour l'adapter à vos besoins.
[!] Important : Tous les paramètres et options de configuration énumérés ci-dessous doivent être enchaînés (mis les uns après les autres) pour lancer gunicorn et servir votre application. Vous ne pouvez pas modifier l'une des options après le lancement du serveur. Quelles que soient les options que vous utilisez, elles doivent être suivies du fichier wsgi contenant le point d'entrée de votre application.
Exemple :
Simply running the server (as shown above):
gunicorn -b 0.0.0.0:8080 wsgi
Running the server with five workers:
gunicorn -b 0.0.0.0:8080 --workers=5 wsgi
Nombre de travailleurs
En général, on considère (et on accepte) que les applications sont plutôt limitées par les entrées/sorties que par le processeur. Ce que cela signifie, c'est que le goulot d'étranglement n'est pas causé par la puissance de traitement de votre serveur virtuel, mais plutôt par les disques. L'idée est la suivante : lorsque qu'un travailleur est occupé avec les opérations sur le disque, un autre utilise toujours le processeur pour traiter les requêtes.
Par conséquent, le nombre suggéré de travailleurs à avoir est généralement fixé autour de la formule simple suivante :
(2 Workers * CPU Cores) + 1
---------------------------
For 1 core -> (2*1)+1 = 3
For 2 cores -> (2*2)+1 = 5
For 4 cores -> (2*4)+1 = 9
Vous pouvez spécifier le nombre de travailleurs en passant l'argument --workers=[n].
Utilisation :
Example: gunicorn --workers=[number of workers]
gunicorn --workers=5
Remarque : Le scénario ci-dessus ne s'applique pas strictement aux travailleurs non-bloquants.
Paramètres de la prise
Le fonctionnement des liaisons de sockets est le suivant :
Example: gunicorn -b [address:port]
gunicorn -b 127.0.0.1:8080
Remarque : Lorsqu'une application est configurée pour écouter les connexions entrantes sur
127.0.0.1, il ne sera possible de l'accéder que localement. Si vous utilisez0.0.0.0, en revanche, elle acceptera également des connexions de l'extérieur.
Sélectionner le type de travailleur
Gunicorn, comme nous l'avons discuté, offrait la possibilité de travailler avec différents types de travailleurs.
Pour la majorité des déploiements, le type de travailleur standard - sync - sera suffisant et est fourni par défaut, il ne nécessite donc aucun paramétrage explicite.
Pour les autres travailleurs, veuillez noter que vous devrez les installer en tant que dépendances.
Utilisation :
Example: gunicorn -k [worker]
gunicorn -k sync # or;
gunicorn -k gevent # ..
Types disponibles :
- synchroniser
- événementiel
- gevent
- tornade
Nombre de connexions simultanées pour Eventlet/Gevent
Pour modifier le nombre de connexions simultanées pour les travailleurs Eventlet et Gevent :
Example: gunicorn -k [worker] --worker-connections [number]
gunicorn -k gevent --worker-connections 1001
Journaux d'accès
Si vous souhaitez définir explicitement le fichier pour enregistrer les journaux d'accès :
Example: gunicorn --access-logfile [file]
gunicorn --access-logfile acclogs
Par défaut, cette option est définie sur Aucune.
Journaux d'erreurs
Pour spécifier un fichier dans lequel enregistrer les journaux d'erreurs, utilisez ce paramètre.
Example: gunicorn --log-file [file]
gunicorn --log-file error_logs.log
Niveau de Journalisation
Cela est utilisé pour définir la granularité des sorties du journal des erreurs. Les options possibles sont :
- déboguer
- info
- avertissement
- erreur
- critique
Utilisation :
# Example: gunicorn --log-level [level]
gunicorn --log-level error
Nommer le processus
Si vous utilisez des utilitaires tels que top pour surveiller vos processus, vous pouvez utiliser ce paramètre pour leur donner un nom plus significatif, ce qui devrait vous aider dans votre tâche.
Example: gunicorn --name [name]
gunicorn --name my_application
Configurer Nginx
Après avoir appris à configurer et à exécuter Gunicorn, nous devons maintenant faire de même avec Nginx pour communiquer avec le serveur Gunicorn exécutant l'application. Pour cela, nous devons modifier le fichier de configuration de Nginx : nginx.conf.
Exécutez la commande suivante pour ouvrir “nginx.conf” et l'éditer en utilisant l'éditeur de texte nano :
sudo nano /etc/nginx/nginx.conf
Ensuite, vous pouvez remplacer le fichier par l'exemple de configuration suivant afin de faire fonctionner Nginx en tant que reverse-proxy, communiquant avec votre application.
Remarque : Pour en savoir plus sur l'intégration du support SSL, veuillez lire d'abord cet article : Créer un certificat SSL sur Nginx.
Exemple de configuration pour des applications web :
worker_processes 1;
events {
worker_connections 1024;
}
http {
sendfile on;
gzip on;
gzip_http_version 1.0;
gzip_proxied any;
gzip_min_length 500;
gzip_disable "MSIE [1-6]\.";
gzip_types text/plain text/xml text/css
text/comma-separated-values
text/javascript
application/x-javascript
application/atom+xml;
# Configuration containing list of application servers
upstream app_servers {
server 127.0.0.1:8080;
# server 127.0.0.1:8081;
# ..
# .
}
# Configuration for Nginx
server {
# Running port
listen 80;
# Settings to serve static files
location ^~ /static/ {
# Example:
# root /full/path/to/application/static/file/dir;
root /app/static/;
}
# Serve a static file (ex. favico)
# outside /static directory
location = /favico.ico {
root /app/favico.ico;
}
# Proxy connections to the application servers
# app_servers
location / {
proxy_pass http://app_servers;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}
Lorsque vous avez terminé de modifier la configuration, appuyez sur CTRL+X et confirmez par Y pour sauvegarder et quitter. Vous devrez redémarrer Nginx pour que les modifications prennent effet.
Exécutez ce qui suit pour redémarrer Nginx :
sudo service nginx stop
sudo service nginx start
Remarque : Pour en savoir plus sur Nginx, veuillez consulter notre article : Comment configurer un serveur Web Nginx sur un VPS.
Conseils et suggestions divers
Pare-feu :
- Configurer un pare-feu en utilisant IP Tables
Sécuriser SSH :
- Comment protéger SSH avec fail2ban sur Ubuntu
- Comment protéger SSH avec fail2ban sur CentOS 6
Créer des alertes :
- Comment envoyer des alertes par e-mail sur un VPS CentOS pour la surveillance système
Surveiller et vérifier les journaux d'accès du serveur quotidiennement :
- Comment installer et utiliser Logwatch, l'outil d'analyse et de rapport de logs