Comment servir les applications Flask avec Gunicorn et Nginx sur Ubuntu 18.04

introduction

Dans ce guide, vous allez créer une application Python à l'aide du microframework Flask sur Ubuntu 18.04. L'essentiel de cet article portera sur la configuration desGunicorn application server et sur la façon de lancer l'application et de configurerNginx pour agir en tant que proxy inverse frontal.

Conditions préalables

Avant de commencer ce guide, vous devriez avoir:

  • Un serveur avec Ubuntu 18.04 installé et un utilisateur non root avec des privilèges sudo. Suivez nosinitial server setup guide pour obtenir des conseils.

  • Nginx installé, en suivant les étapes 1 et 2 deHow To Install Nginx on Ubuntu 18.04.

  • Un nom de domaine configuré pour pointer vers votre serveur. Vous pouvez en acheter un surNamecheap ou en obtenir un gratuitement surFreenom. Vous pouvez apprendre à pointer des domaines vers DigitalOcean en suivant lesdocumentation on domains and DNS appropriés. Assurez-vous de créer les enregistrements DNS suivants:

    • Un enregistrement A avecyour_domain pointant vers l'adresse IP publique de votre serveur.

    • Un enregistrement A avecwww.your_domain pointant vers l'adresse IP publique de votre serveur.

  • Familiarité avec la spécification WSGI, que le serveur Gunicorn utilisera pour communiquer avec votre application Flask. This discussion couvre WSGI plus en détail.

[[step-1 -—- installation-des-composants-from-the-ubuntu-repositories]] == Étape 1 - Installation des composants à partir des référentiels Ubuntu

Notre première étape sera d'installer toutes les pièces dont nous avons besoin à partir des référentiels Ubuntu. Cela inclutpip, le gestionnaire de packages Python, qui gérera nos composants Python. Nous obtiendrons également les fichiers de développement Python nécessaires à la création de certains composants Gunicorn.

Commençons par mettre à jour l’index de paquetage local et installons les paquetages qui nous permettront de construire notre environnement Python. Ceux-ci comprendrontpython3-pip, ainsi que quelques autres packages et outils de développement nécessaires à un environnement de programmation robuste:

sudo apt update
sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools

Avec ces packages en place, passons à la création d’un environnement virtuel pour notre projet.

[[step-2 -—- creating-a-python-virtual-environment]] == Étape 2 - Création d'un environnement virtuel Python

Nous allons ensuite configurer un environnement virtuel afin d’isoler notre application Flask des autres fichiers Python du système.

Commencez par installer le packagepython3-venv, qui installera le modulevenv:

sudo apt install python3-venv

Ensuite, créons un répertoire parent pour notre projet Flask. Déplacez-vous dans le répertoire après l'avoir créé:

mkdir ~/myproject
cd ~/myproject

Créez un environnement virtuel pour stocker les exigences Python de votre projet Flask en tapant:

python3.6 -m venv myprojectenv

Cela installera une copie locale de Python et depip dans un répertoire appelémyprojectenv dans le répertoire de votre projet.

Avant d'installer des applications dans l'environnement virtuel, vous devez l'activer. Faites-le en tapant:

source myprojectenv/bin/activate

Votre invite changera pour indiquer que vous travaillez maintenant dans l'environnement virtuel. Cela ressemblera à quelque chose comme ceci:(myprojectenv)user@host:~/myproject$.

[[step-3 -—- setting-up-a-flask-application]] == Étape 3 - Configuration d'une application Flask

Maintenant que vous êtes dans votre environnement virtuel, vous pouvez installer Flask et Gunicorn et commencer à concevoir votre application.

Tout d’abord, installonswheel avec l’instance locale depip pour nous assurer que nos packages s’installeront même s’il manque des archives wheel:

pip install wheel

Note

[.note] # Quelle que soit la version de Python que vous utilisez, lorsque l'environnement virtuel est activé, vous devez utiliser la commandepip (et nonpip3).
#

Ensuite, installons Flask and Gunicorn:

pip install gunicorn flask

Création d'un exemple d'application

Maintenant que Flask est disponible, vous pouvez créer une application simple. Flask est un microframework. Il n'inclut pas la plupart des outils que pourraient implémenter des infrastructures plus complètes, et existe principalement sous forme de module que vous pouvez importer dans vos projets pour vous aider à initialiser une application Web.

Bien que votre application soit plus complexe, nous créerons notre application Flask dans un seul fichier, appelémyproject.py:

nano ~/myproject/myproject.py

Le code de l'application vivra dans ce fichier. Il importera Flask et instanciera un objet Flask. Vous pouvez l'utiliser pour définir les fonctions à exécuter lorsqu'un itinéraire spécifique est demandé:

~/myproject/myproject.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "

Hello There!

" if __name__ == "__main__": app.run(host='0.0.0.0')

Cela définit essentiellement le contenu à présenter lors de l'accès au domaine racine. Enregistrez et fermez le fichier lorsque vous avez terminé.

Si vous avez suivi le guide de configuration initiale du serveur, vous devez activer un pare-feu UFW. Pour tester l'application, vous devez autoriser l'accès au port5000:

sudo ufw allow 5000

Vous pouvez maintenant tester votre application Flask en tapant:

python myproject.py

Vous verrez une sortie comme celle-ci, avec un avertissement utile vous rappelant de ne pas utiliser cette configuration de serveur en production:

Output* Serving Flask app "myproject" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

Accédez à l'adresse IP de votre serveur suivie de:5000 dans votre navigateur Web:

http://your_server_ip:5000

Vous devriez voir quelque chose comme ça:

Flask sample app

Lorsque vous avez terminé, appuyez surCTRL-C dans la fenêtre de votre terminal pour arrêter le serveur de développement Flask.

Création du point d'entrée WSGI

Ensuite, créons un fichier qui servira de point d’entrée pour notre application. Cela indiquera à notre serveur Gunicorn comment interagir avec l'application.

Appelons le fichierwsgi.py:

nano ~/myproject/wsgi.py

Dans ce fichier, importons l’instance Flask de notre application, puis exécutons-la:

~/myproject/wsgi.py

from myproject import app

if __name__ == "__main__":
    app.run()

Enregistrez et fermez le fichier lorsque vous avez terminé.

[[step-4 -—- configuring-gunicorn]] == Étape 4 - Configuration de Gunicorn

Votre application est maintenant écrite avec un point d’entrée établi. Nous pouvons maintenant passer à la configuration de Gunicorn.

Avant de poursuivre, nous devrions vérifier que Gunicorn peut servir correctement l’application.

Nous pouvons le faire en lui donnant simplement le nom de notre point d’entrée. Ceci est construit comme le nom du module (moins l'extension.py), plus le nom de l'appelable dans l'application. Dans notre cas, il s'agit dewsgi:app.

Nous spécifierons également l’interface et le port auxquels vous souhaitez vous connecter afin que l’application puisse démarrer sur une interface accessible au public:

cd ~/myproject
gunicorn --bind 0.0.0.0:5000 wsgi:app

Vous devriez voir une sortie comme celle-ci:

Output[2018-07-13 19:35:13 +0000] [28217] [INFO] Starting gunicorn 19.9.0
[2018-07-13 19:35:13 +0000] [28217] [INFO] Listening at: http://0.0.0.0:5000 (28217)
[2018-07-13 19:35:13 +0000] [28217] [INFO] Using worker: sync
[2018-07-13 19:35:13 +0000] [28220] [INFO] Booting worker with pid: 28220

Accédez à nouveau à l'adresse IP de votre serveur avec:5000 ajouté à la fin dans votre navigateur Web:

http://your_server_ip:5000

Vous devriez voir la sortie de votre application:

Flask sample app

Lorsque vous avez confirmé qu'il fonctionne correctement, appuyez surCTRL-C dans la fenêtre de votre terminal.

Nous en avons terminé avec notre environnement virtuel. Nous pouvons donc le désactiver:

deactivate

Toutes les commandes Python utiliseront à nouveau l’environnement Python du système.

Ensuite, créons le fichier d’unité de service systemd. La création d’un fichier unité systemd permettra au système init d’Ubuntu de démarrer automatiquement Gunicorn et de servir l’application Flask à chaque démarrage du serveur.

Créez un fichier unité se terminant par.service dans le répertoire/etc/systemd/system pour commencer:

sudo nano /etc/systemd/system/myproject.service

À l'intérieur, nous commencerons par la section[Unit], qui est utilisée pour spécifier les métadonnées et les dépendances. Mettons ici une description de notre service et disons au système init de ne le démarrer que lorsque la cible réseau aura été atteinte:

/etc/systemd/system/myproject.service

[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

Ensuite, ouvrons la section[Service]. Cela spécifiera l'utilisateur et le groupe sous lesquels nous voulons que le processus s'exécute. Donnons à notre compte utilisateur régulier la propriété du processus car il possède tous les fichiers pertinents. Donnons également la propriété du groupe au groupewww-data afin que Nginx puisse communiquer facilement avec les processus Gunicorn. N'oubliez pas de remplacer le nom d'utilisateur ici par votre nom d'utilisateur:

/etc/systemd/system/myproject.service

[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data

Ensuite, cartographions le répertoire de travail et définissons la variable d'environnementPATH afin que le système init sache que les exécutables du processus se trouvent dans notre environnement virtuel. Spécifions également la commande pour démarrer le service. Cette commande va faire ce qui suit:

  • Démarrer 3 processus de travail (bien que vous devriez ajuster ceci si nécessaire)

  • Créez et liez un fichier socket Unix,myproject.sock, dans notre répertoire de projet. Nous allons définir une valeur umask de007 pour que le fichier socket soit créé, donnant accès au propriétaire et au groupe, tout en restreignant les autres accès

  • Spécifiez le nom du fichier du point d'entrée WSGI, ainsi que le Python appelable dans ce fichier (wsgi:app)

Systemd nécessite que nous donnions le chemin complet au fichier exécutable Gunicorn, qui est installé dans notre environnement virtuel.

N'oubliez pas de remplacer le nom d'utilisateur et les chemins du projet par vos propres informations:

/etc/systemd/system/myproject.service

[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app

Enfin, ajoutons une section[Install]. Cela indiquera à systemd à quoi lier ce service si nous lui permettons de démarrer au démarrage. Nous voulons que ce service démarre lorsque le système multi-utilisateurs normal est opérationnel:

/etc/systemd/system/myproject.service

[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app

[Install]
WantedBy=multi-user.target

Avec cela, notre fichier de service systemd est complet. Enregistrez et fermez-le maintenant.

Nous pouvons maintenant démarrer le service Gunicorn que nous avons créé et l'activer pour qu'il démarre au démarrage:

sudo systemctl start myproject
sudo systemctl enable myproject

Voyons l’état:

sudo systemctl status myproject

Vous devriez voir la sortie comme ceci:

Output● myproject.service - Gunicorn instance to serve myproject
   Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2018-07-13 14:28:39 UTC; 46s ago
 Main PID: 28232 (gunicorn)
    Tasks: 4 (limit: 1153)
   CGroup: /system.slice/myproject.service
           ├─28232 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007
           ├─28250 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007
           ├─28251 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007
           └─28252 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007

Si vous voyez des erreurs, assurez-vous de les résoudre avant de poursuivre le didacticiel.

[[step-5 -—- configuring-nginx-to-proxy-requests]] == Étape 5 - Configuration de Nginx en requêtes proxy

Notre serveur d’applications Gunicorn devrait maintenant être opérationnel et attendre les demandes sur le fichier de socket dans le répertoire du projet. Configurons maintenant Nginx pour transmettre les requêtes Web à ce socket en apportant de petits ajouts à son fichier de configuration.

Commencez par créer un nouveau fichier de configuration de bloc serveur dans le répertoiresites-available de Nginx. Appelons cecimyproject pour rester en ligne avec le reste du guide:

sudo nano /etc/nginx/sites-available/myproject

Ouvrez un bloc serveur et dites à Nginx d'écouter sur le port par défaut80. Dites-lui également d’utiliser ce bloc pour les demandes de nom de domaine de notre serveur:

/etc/nginx/sites-available/myproject

server {
    listen 80;
    server_name your_domain www.your_domain;
}

Ensuite, ajoutons un bloc d’emplacement correspondant à chaque demande. Dans ce bloc, nous inclurons le fichierproxy_params qui spécifie certains paramètres généraux de proxy qui doivent être définis. Nous passerons ensuite les requêtes au socket que nous avons défini à l'aide de la directiveproxy_pass:

/etc/nginx/sites-available/myproject

server {
    listen 80;
    server_name your_domain www.your_domain;

    location / {
        include proxy_params;
        proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
    }
}

Enregistrez et fermez le fichier lorsque vous avez terminé.

Pour activer la configuration de bloc de serveur Nginx que vous venez de créer, liez le fichier au répertoiresites-enabled:

sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

Avec le fichier dans ce répertoire, vous pouvez tester les erreurs de syntaxe:

sudo nginx -t

Si cela retourne sans indiquer de problème, redémarrez le processus Nginx pour lire la nouvelle configuration:

sudo systemctl restart nginx

Enfin, ajustons à nouveau le pare-feu. Nous n'avons plus besoin d'accéder via le port5000, nous pouvons donc supprimer cette règle. Nous pouvons ensuite autoriser un accès complet au serveur Nginx:

sudo ufw delete allow 5000
sudo ufw allow 'Nginx Full'

Vous devriez maintenant pouvoir accéder au nom de domaine de votre serveur dans votre navigateur Web:

http://your_domain

Vous devriez voir la sortie de votre application:

Flask sample app

Si vous rencontrez des erreurs, essayez de vérifier les éléments suivants:

  • sudo less /var/log/nginx/error.log: vérifie les journaux d'erreurs Nginx.

  • sudo less /var/log/nginx/access.log: vérifie les journaux d'accès Nginx.

  • sudo journalctl -u nginx: vérifie les journaux de processus Nginx.

  • sudo journalctl -u myproject: vérifie les journaux Gunicorn de votre application Flask.

[[step-6 -—- secure-the-application]] == Étape 6 - Sécurisation de l'application

Pour vous assurer que le trafic sur votre serveur reste sécurisé, obtenons un certificat SSL pour votre domaine. Il existe plusieurs façons de le faire, y compris l'obtention d'un certificat gratuit deLet’s Encrypt,generating a self-signed certificate oubuying one from another provider et la configuration de Nginx pour l'utiliser en suivant les étapes 2 à 6 deHow to Create a Self-signed SSL Certificate for Nginx in Ubuntu 18.04 . Nous allons choisir l’option 1 par souci d’opportunité.

Premièrement, ajoutez le référentiel Certbot Ubuntu:

sudo add-apt-repository ppa:certbot/certbot

Vous devrez appuyer surENTER pour accepter.

Installez le package Nginx de Certbot avecapt:

sudo apt install python-certbot-nginx

Certbot propose diverses méthodes pour obtenir des certificats SSL via des plugins. Le plugin Nginx se chargera de reconfigurer Nginx et de recharger la configuration chaque fois que nécessaire. Pour utiliser ce plugin, tapez ce qui suit:

sudo certbot --nginx -d your_domain -d www.your_domain

Cela exécutecertbot avec le plugin--nginx, en utilisant-d pour spécifier les noms pour lesquels nous aimerions que le certificat soit valide.

Si c'est la première fois que vous exécutezcertbot, vous serez invité à saisir une adresse e-mail et à accepter les conditions d'utilisation. Après cela,certbot communiquera avec le serveur Let’s Encrypt, puis lancera un défi pour vérifier que vous contrôlez le domaine pour lequel vous demandez un certificat.

Si cela réussit,certbot vous demandera comment vous souhaitez configurer vos paramètres HTTPS:

OutputPlease choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

Sélectionnez votre choix puis appuyez surENTER. La configuration sera mise à jour et Nginx se rechargera pour récupérer les nouveaux paramètres. certbot se terminera par un message vous indiquant que le processus a réussi et où vos certificats sont stockés:

OutputIMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/your_domain/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/your_domain/privkey.pem
   Your cert will expire on 2018-07-23. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Si vous avez suivi les instructions d'installation de Nginx dans les conditions préalables, vous n'aurez plus besoin de la tolérance de profil HTTP redondant:

sudo ufw delete allow 'Nginx HTTP'

Pour vérifier la configuration, accédez à nouveau à votre domaine en utilisanthttps://:

https://your_domain

Vous devriez voir à nouveau la sortie de votre application, ainsi que l'indicateur de sécurité de votre navigateur, ce qui devrait indiquer que le site est sécurisé.

Conclusion

Dans ce guide, vous avez créé et sécurisé une application Flask simple dans un environnement virtuel Python. Vous avez créé un point d'entrée WSGI afin que tout serveur d'applications compatible WSGI puisse s'y connecter, puis vous avez configuré le serveur d'applications Gunicorn pour fournir cette fonction. Ensuite, vous avez créé un fichier de service systemd pour lancer automatiquement le serveur d'applications au démarrage. Vous avez également créé un bloc de serveur Nginx qui transfère le trafic du client Web au serveur d'applications, en relayant les demandes externes, et en sécurisant le trafic sur votre serveur avec Let’s Encrypt.

Flask est un framework très simple, mais extrêmement flexible, destiné à fournir des fonctionnalités à vos applications sans être trop restrictif en termes de structure et de conception. Vous pouvez utiliser la pile générale décrite dans ce guide pour servir les applications de flacon que vous concevez.

Related