A previous version of this tutorial was written by Kathleen Juell.
Introduction
Dans ce guide, vous allez créer une application Python en utilisant le micro-framework Flask sur Ubuntu 22.04. La majeure partie de ce tutoriel portera sur la configuration du serveur d’application Gunicorn et sur la manière de lancer l’application et de configurer Nginx pour qu’il agisse en tant que proxy inverse frontal.
Prérequis
Avant de commencer ce guide, vous devez avoir :
-
Un serveur avec Ubuntu 22.04 installé et un utilisateur non root avec des privilèges sudo. Suivez notre guide de configuration initiale du serveur pour des instructions.
-
Nginx installé, en suivant les étapes 1 et 2 de Comment installer Nginx sur Ubuntu 22.04.
-
Un nom de domaine configuré pour pointer vers votre serveur. Vous pouvez en acheter un sur Namecheap ou en obtenir un gratuitement sur Freenom. Vous pouvez apprendre comment pointer des domaines vers DigitalOcean en suivant la documentation pertinente sur les domaines et le DNS. Assurez-vous de créer les enregistrements DNS suivants :
- Un enregistrement A avec
votre_domaine
pointant vers l’adresse IP publique de votre serveur. - Un enregistrement A avec
www.votre_domaine
pointant vers l’adresse IP publique de votre serveur.
- Un enregistrement A avec
-
Familiarisez-vous avec la spécification WSGI, que le serveur Gunicorn utilisera pour communiquer avec votre application Flask. Cette discussion couvre le WSGI plus en détail.
Étape 1 — Installation des composants depuis les dépôts Ubuntu
La première étape consistera à installer tous les éléments requis depuis les dépôts Ubuntu. Cela inclut pip
, le gestionnaire de paquets Python, qui gérera les composants Python. Vous obtiendrez également les fichiers de développement Python nécessaires pour construire certains des composants Gunicorn.
Tout d’abord, mettez à jour l’index des paquets locaux et installez les paquets qui vous permettront de construire votre environnement Python. Cela inclura python3-pip
, ainsi que quelques autres paquets et outils de développement nécessaires pour un environnement de programmation robuste :
Avec ces paquets en place, la prochaine étape consiste à créer un environnement virtuel pour votre projet.
Étape 2 — Création d’un environnement virtuel Python
Ensuite, vous configurerez un environnement virtuel afin d’isoler l’application Flask des autres fichiers Python sur votre système.
Commencez par installer le paquet python3-venv
, qui installera le module venv
:
Ensuite, créez un répertoire parent pour votre projet Flask. Déplacez-vous dans le répertoire avec la commande cd
après l’avoir créé :
Créez un environnement virtuel pour stocker les besoins en Python de votre projet Flask en tapant :
Cela installera une copie locale de Python et de pip
dans un répertoire appelé myprojectenv
à l’intérieur de votre répertoire de projet.
Avant d’installer des applications dans l’environnement virtuel, vous devez l’activer. Faites-le en tapant :
Votre invite changera pour indiquer que vous travaillez maintenant dans l’environnement virtuel. Cela ressemblera à ceci : (myprojectenv)user@host:~/myproject$
.
É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, installez wheel
avec l’instance locale de pip
pour vous assurer que vos paquets s’installeront même s’ils manquent d’archives wheel :
Remarque
Peu importe la version de Python que vous utilisez, lorsque l’environnement virtuel est activé, vous devez utiliser la commande pip
(et non pip3
).
Ensuite, installez Flask et Gunicorn :
Création d’une application d’exemple
Maintenant que vous avez Flask disponible, vous pouvez créer une application simple. Flask est un micro-framework. Il ne comprend pas de nombreux outils que pourraient inclure des frameworks plus complets, et existe principalement sous forme de module que vous pouvez importer dans vos projets pour vous aider à initialiser une application web.
Alors que votre application pourrait être plus complexe, nous allons créer notre application Flask dans un seul fichier, appelé monprojet.py
:
Le code de l’application vivra dans ce fichier. Il importera Flask et instanciera un objet Flask. Vous pouvez utiliser cela pour définir les fonctions qui doivent être exécutées lorsqu’une route spécifique est demandée :
Cela définit essentiellement quel contenu présenter lorsque le domaine racine est accédé. Enregistrez et fermez le fichier lorsque vous avez fini.
Si vous avez suivi le guide de configuration initiale du serveur, vous devriez avoir un pare-feu UFW activé. Pour tester l’application, vous devez autoriser l’accès au port 5000
:
Maintenant, vous pouvez tester votre application Flask en tapant :
Vous verrez une sortie comme celle-ci, comprenant 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)
Visitez l’adresse IP de votre serveur suivie de :5000
dans votre navigateur web :
http://your_server_ip:5000
Vous devriez voir quelque chose comme ceci :
Lorsque vous avez fini, appuyez sur CTRL-C
dans votre fenêtre de terminal pour arrêter le serveur de développement Flask.
Création du point d’entrée WSGI
Ensuite, créez un fichier qui servira de point d’entrée pour votre application. Cela indiquera au serveur Gunicorn comment interagir avec l’application.
Appelez le fichier wsgi.py
:
Dans ce fichier, importez l’instance Flask de notre application, puis exécutez-la :
Enregistrez et fermez le fichier lorsque vous avez terminé.
Étape 4 — Configuration de Gunicorn
Votre application est maintenant écrite avec un point d’entrée établi. Vous pouvez maintenant passer à la configuration de Gunicorn.
Avant de continuer, vérifiez que Gunicorn peut servir correctement l’application.
Vous pouvez le faire en lui passant le nom du point d’entrée de l’application. Celui-ci est construit comme le nom du module (moins l’extension .py
), plus le nom de l’appelable dans l’application. Dans ce cas, c’est wsgi:app
.
Spécifiez également l’interface et le port auquel se lier en utilisant l’argument 0.0.0.0:5000
afin que l’application soit démarrée sur une interface disponible publiquement :
Vous devriez voir une sortie comme celle-ci :
Output[2020-05-20 14:13:00 +0000] [46419] [INFO] Starting gunicorn 20.0.4
[2020-05-20 14:13:00 +0000] [46419] [INFO] Listening at: http://0.0.0.0:5000 (46419)
[2020-05-20 14:13:00 +0000] [46419] [INFO] Using worker: sync
[2020-05-20 14:13:00 +0000] [46421] [INFO] Booting worker with pid: 46421
Visitez à 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 :
Lorsque vous avez confirmé que tout fonctionne correctement, appuyez sur CTRL-C
dans votre fenêtre de terminal.
Lorsque vous avez terminé d’utiliser l’environnement virtuel, vous pouvez le désactiver :
Toutes les commandes Python utiliseront à nouveau l’environnement Python du système.
Ensuite, créez le fichier d’unité de service systemd. La création d’un fichier d’unité systemd permettra au système d’initialisation d’Ubuntu de démarrer automatiquement Gunicorn et de servir l’application Flask chaque fois que le serveur démarre.
Créez un fichier d’unité se terminant par .service
dans le répertoire /etc/systemd/system
pour commencer :
À l’intérieur, vous commencerez par la section [Unit]
, qui est utilisée pour spécifier les métadonnées et les dépendances. Ajoutez une description de votre service ici et indiquez au système d’initialisation de démarrer ceci uniquement après que la cible de réseau a été atteinte :
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
Ensuite, ajoutez une section [Service]
. Cela spécifiera l’utilisateur et le groupe sous lesquels vous souhaitez que le processus s’exécute. Donnez à votre compte utilisateur régulier la propriété du processus car il possède tous les fichiers pertinents. Donnez également la propriété du groupe au groupe www-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 :
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
Ensuite, cartographiez le répertoire de travail et définissez la variable d’environnement PATH
afin que le système d’initialisation sache que les exécutables du processus se trouvent dans notre environnement virtuel. Spécifiez également la commande pour démarrer le service. Cette commande fera ce qui suit :
- Démarrer 3 processus de travail (mais vous devriez ajuster cela si nécessaire)
- Créer et se lier à un fichier de socket Unix,
myproject.sock
, à l’intérieur de notre répertoire de projet. Nous définirons une valeur de masque umask de007
afin que le fichier de socket soit créé en donnant accès au propriétaire et au groupe, tout en restreignant l’accès aux autres - Spécifier le nom du fichier d’entrée du point WSGI, ainsi que le callable Python dans ce fichier (
wsgi:app
)
Systemd exige que vous fournissiez le chemin complet vers l’exécutable Gunicorn, qui est installé dans votre environnement virtuel.
N’oubliez pas de remplacer le nom d’utilisateur et les chemins du projet par vos propres informations :
[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, ajoutez une section [Install]
. Cela indiquera à systemd à quoi lier ce service si vous le configurez pour démarrer au démarrage. Vous voudrez que ce service démarre lorsque le système multi-utilisateurs régulier est opérationnel :
[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, votre fichier de service systemd est complet. Enregistrez-le et fermez-le maintenant.
Vous pouvez maintenant démarrer le service Gunicorn que vous avez créé et le rendre activé pour qu’il démarre au démarrage :
Vérifions l’état :
Vous devriez voir une 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 Tue 2022-05-10 19:40:41 UTC; 9s ago
Main PID: 17300 (gunicorn)
Tasks: 4 (limit: 2327)
Memory: 56.0M
CPU: 514ms
CGroup: /system.slice/myproject.service
├─17300 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─17301 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─17302 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
└─17303 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
May 10 19:40:41 r systemd[1]: Started Gunicorn instance to serve myproject.
. . .
Si vous rencontrez des erreurs, assurez-vous de les résoudre avant de continuer avec le tutoriel.
Étape 5 — Configuration de Nginx pour Proxifier les Requêtes
Votre serveur d’application Gunicorn devrait maintenant être en cours d’exécution, en attente de requêtes sur le fichier socket dans le répertoire du projet. Maintenant, vous pouvez configurer Nginx pour transmettre les requêtes Web à ce socket en apportant quelques petites modifications à son fichier de configuration.
Commencez par créer un nouveau fichier de configuration de bloc serveur dans le répertoire sites-available
de Nginx. Appelez-le monprojet
pour rester cohérent avec le reste du guide:
Ouvrez un bloc serveur et indiquez à Nginx d’écouter sur le port par défaut 80
. Indiquez également d’utiliser ce bloc pour les requêtes concernant le nom de domaine de notre serveur:
server {
listen 80;
server_name your_domain www.your_domain;
}
Ensuite, ajoutez un bloc de localisation qui correspond à chaque requête. Dans ce bloc, incluez le fichier proxy_params
qui spécifie quelques paramètres de proxification généraux à définir. Puis transmettez les requêtes au socket que vous avez défini en utilisant la directive proxy_pass
:
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 serveur Nginx que vous venez de créer, liez le fichier au répertoire sites-enabled
:
Avec le fichier dans ce répertoire, vous pouvez tester les erreurs de syntaxe:
Si cela ne signale aucun problème, redémarrez le processus Nginx pour lire la nouvelle configuration:
Enfin, ajustez à nouveau le pare-feu. Vous n’avez plus besoin d’accéder via le port 5000
, vous pouvez donc supprimer cette règle. Vous pouvez ensuite autoriser un accès complet au serveur Nginx:
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:
Note: Vous recevrez une erreur de passerelle HTTP 502 si Nginx ne peut pas accéder au fichier de socket de gunicorn. Habituellement, cela est dû au fait que le répertoire personnel de l’utilisateur n’autorise pas les autres utilisateurs à accéder aux fichiers à l’intérieur.
Si votre fichier de socket est appelé /home/sammy/myproject/myproject.sock
, assurez-vous que /home/sammy
a au moins les permissions 0755
. Vous pouvez utiliser un outil comme chmod
pour changer les permissions comme ceci:
Ensuite, rechargez la page pour voir si l’erreur HTTP 502 disparaît.
Si vous rencontrez des erreurs, essayez de vérifier ce qui suit:
sudo less /var/log/nginx/error.log
: vérifie les journaux d’erreur de Nginx.sudo less /var/log/nginx/access.log
: vérifie les journaux d’accès de Nginx.sudo journalctl -u nginx
: vérifie les journaux du processus Nginx.sudo journalctl -u myproject
: vérifie les journaux Gunicorn de votre application Flask.
Étape 6 — Sécurisation de l’Application
Pour garantir que le trafic vers votre serveur reste sécurisé, obtenons un certificat SSL pour votre domaine. Il existe plusieurs façons de le faire, notamment en obtenant un certificat gratuit de Let’s Encrypt, en générant un certificat auto-signé, ou en en achetant un auprès d’un autre fournisseur et en configurant Nginx pour l’utiliser en suivant les étapes 2 à 6 de Comment créer un certificat SSL auto-signé pour Nginx dans Ubuntu 22.04. Nous utiliserons l’option un (Let’s Encrypt) pour des raisons de rapidité.
Installez le paquet Nginx de Certbot avec apt
:
Certbot propose diverses façons d’obtenir des certificats SSL via des plugins. Le plugin Nginx se chargera de reconfigurer Nginx et de recharger la configuration lorsque nécessaire. Pour utiliser ce plugin, tapez ce qui suit :
Cela exécute certbot
avec le plugin --nginx
, en utilisant -d
pour spécifier les noms pour lesquels le certificat doit être valide.
Si c’est la première fois que vous exécutez certbot
, vous serez invité à saisir une adresse e-mail et à accepter les conditions d’utilisation. Après avoir fait 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 sur ENTRÉE
. La configuration sera mise à jour et Nginx se rechargera pour prendre en compte les nouveaux paramètres. certbot
conclura en vous indiquant que le processus a été un succès et où sont stockés vos certificats :
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 2020-08-18. 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 prérequis, vous n’aurez plus besoin du profil HTTP redondant :
Pour vérifier la configuration, naviguez à nouveau vers votre domaine en utilisant https://
:
https://your_domain
Vous devriez voir à nouveau la sortie de votre application, ainsi que l’indicateur de sécurité de votre navigateur, 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 n’importe quel serveur d’application compatible WSGI puisse interagir avec celui-ci, puis configuré le serveur d’application Gunicorn pour fournir cette fonctionnalité. Ensuite, vous avez créé un fichier de service systemd pour lancer automatiquement le serveur d’application au démarrage. Vous avez également créé un bloc serveur Nginx qui redirige le trafic des clients web vers le serveur d’application, relayant les demandes externes, et sécurisé le trafic vers votre serveur avec Let’s Encrypt.
Flask est un framework très simple mais extrêmement flexible conçu pour fournir à vos applications des fonctionnalités 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 Flask que vous concevez.