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

introduction

Dans ce guide, nous allons configurer une application Python simple en utilisant le micro-framework Flask sur Ubuntu 16.04. La majeure partie de cet article traitera de la configuration du serveur d’applications Gunicorn pour le lancement de l’application et de Nginx pour qu’il agisse en tant que proxy inverse frontal.

Conditions préalables

Avant de commencer ce guide, vous devez avoir un utilisateur non root configuré sur votre serveur. Cet utilisateur doit disposer des privilègessudo pour pouvoir effectuer des fonctions administratives. Pour savoir comment configurer cela, suivez nosinitial server setup guide.

Pour en savoir plus sur la spécification WSGI que notre serveur d'application utilisera pour communiquer avec notre application Flask, vous pouvez lire la section liée dethis guide. Comprendre ces concepts rendra ce guide plus facile à suivre.

Lorsque vous êtes prêt à continuer, lisez la suite.

Installer les composants à partir des référentiels Ubuntu

Notre première étape consistera à installer toutes les pièces dont nous avons besoin des référentiels. Nous installeronspip, le gestionnaire de paquets Python, afin d'installer et de gérer nos composants Python. Nous aurons également les fichiers de développement Python nécessaires à la création de certains composants de Gunicorn. Nous allons également installer Nginx.

Mettez à jour votre index de package local, puis installez les packages. Les packages spécifiques dont vous avez besoin dépendent de la version de Python que vous utilisez pour votre projet.

Si vous utilisezPython 2, tapez:

sudo apt-get update
sudo apt-get install python-pip python-dev nginx

Si, à la place, vous utilisezPython 3, tapez:

sudo apt-get update
sudo apt-get install python3-pip python3-dev nginx

Créer 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 packagevirtualenv en utilisantpip.

Si vous utilisezPython 2, tapez:

sudo pip install virtualenv

Si vous utilisezPython 3, tapez:

sudo pip3 install virtualenv

Nous pouvons maintenant créer un répertoire parent pour notre projet Flask. Déplacez-vous dans le répertoire après l'avoir créé:

mkdir ~/myproject
cd ~/myproject

Nous pouvons créer un environnement virtuel pour stocker les exigences Python de notre projet Flask en tapant:

virtualenv 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, nous devons l'activer. Vous pouvez le faire 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$.

Configurer une application de flacon

Maintenant que vous êtes dans votre environnement virtuel, nous pouvons installer Flask et Gunicorn et commencer à concevoir notre application:

Installez Flask et Gunicorn

Nous pouvons utiliser l'instance locale depip pour installer Flask et Gunicorn. Tapez les commandes suivantes pour obtenir ces deux composants:

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).
#

pip install gunicorn flask

Créer un exemple d'application

Maintenant que Flask est disponible, nous pouvons créer une application simple. Flask est un micro-cadre. 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, que nous appelleronsmyproject.py:

nano ~/myproject/myproject.py

Dans ce fichier, nous placerons notre code d'application. Fondamentalement, nous devons importer un flacon et instancier un objet Flask. Nous pouvons utiliser ceci 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. Afin de tester notre application, nous devons autoriser l'accès au port 5000.

Ouvrez le port 5000 en tapant:

sudo ufw allow 5000

Maintenant, vous pouvez tester votre application Flask en tapant:

python myproject.py

Accédez au nom de domaine ou à l'adresse IP de votre serveur, suivi de:5000 dans votre navigateur Web:

http://server_domain_or_IP:5000

Vous devriez voir quelque chose comme ça:

Flask sample app

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

Créer le point d'entrée WSGI

Nous allons ensuite créer un fichier qui servira de point d’entrée pour notre application. Cela indiquera à notre serveur Gunicorn comment interagir avec l'application.

Nous appellerons le fichierwsgi.py:

nano ~/myproject/wsgi.py

Le fichier est incroyablement simple, nous pouvons simplement importer l'instance Flask de notre application puis l'exécuter:

~/myproject/wsgi.py

from myproject import app

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

Enregistrez et fermez le fichier lorsque vous avez terminé.

Tester la capacité de Gunicorn à servir le projet

Avant de continuer, nous devrions vérifier que Gunicorn peut correctement.

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

Nous spécifierons également l’interface et le port auxquels vous souhaitez vous connecter afin qu’elle soit lancée sur une interface accessible au public:

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

Visitez le nom de domaine ou l’adresse IP de votre serveur avec: 5000 ajoutés à la fin de votre navigateur Web:

http://server_domain_or_IP:5000

Vous devriez voir à nouveau la sortie de votre application:

Flask sample app

Une fois que vous avez vérifié qu’il fonctionne correctement, appuyez sur CTRL-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.

Créer un fichier unité systemd

Le fichier suivant de l’unité de service systemd est le suivant. La création d’un fichier unité systemd permettra au système init d’Ubuntu de démarrer automatiquement Gunicorn et de servir notre 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. Nous allons mettre ici une description de notre service et dire au système init de ne le démarrer qu’après avoir atteint la cible réseau:

/etc/systemd/system/myproject.service

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

Ensuite, nous allons ouvrir la section[Service]. Nous spécifierons l'utilisateur et le groupe sous lesquels le processus doit s'exécuter. Nous allons donner à notre compte utilisateur habituel la propriété du processus puisqu'il possède tous les fichiers pertinents. Nous donnerons la propriété du groupe au groupewww-data afin que Nginx puisse communiquer facilement avec les processus Gunicorn.

Nous allons ensuite mapper le répertoire de travail et définir la variable d'environnementPATH afin que le système init sache où se trouvent nos exécutables pour le processus (dans notre environnement virtuel). Nous allons ensuite spécifier le commandé pour démarrer le service. Systemd nécessite que nous donnions le chemin complet au fichier exécutable Gunicorn, qui est installé dans notre environnement virtuel.

Nous lui dirons de démarrer 3 processus de travail (ajustez-le si nécessaire). Nous lui dirons également de créer et de se lier à un fichier socket Unix dans notre répertoire de projet appelémyproject.sock. Nous allons définir une valeur umask de007 afin que le fichier socket soit créé, donnant accès au propriétaire et au groupe, tout en restreignant les autres accès. Enfin, nous devons passer le nom du fichier de point d’entrée WSGI et le nom de fichier pouvant être appelé Python dans:

/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, nous ajouterons 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

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. Nous devons configurer 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. Nous appellerons simplement 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 80 par défaut. Nous devons également lui indiquer d’utiliser ce bloc pour les demandes de nom de domaine ou d’adresse IP de notre serveur:

/etc/nginx/sites-available/myproject

server {
    listen 80;
    server_name server_domain_or_IP;
}

La seule autre chose que nous devons ajouter est un bloc d’emplacement qui correspond à 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 server_domain_or_IP;

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

C’est tout ce dont nous avons besoin pour servir notre application. Enregistrez et fermez le fichier lorsque vous avez terminé.

Pour activer la configuration de bloc de serveur Nginx que nous venons 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, nous pouvons tester les erreurs de syntaxe en tapant:

sudo nginx -t

Si cela retourne sans indiquer de problème, nous pouvons redémarrer le processus Nginx pour lire notre nouvelle configuration:

sudo systemctl restart nginx

La dernière chose à faire est de réajuster notre pare-feu. Nous n'avons plus besoin d'accès via le port 5000, nous pouvons donc supprimer cette règle. Nous pouvons ensuite autoriser l'accès au serveur Nginx:

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

Vous devriez maintenant pouvoir accéder au nom de domaine ou à l’adresse IP de votre serveur dans votre navigateur Web:

http://server_domain_or_IP

Vous devriez voir la sortie de votre application:

Flask sample app

Note

[.Remarque]##

Après avoir configuré Nginx, l'étape suivante devrait être de sécuriser le trafic vers le serveur à l'aide de SSL / TLS. Ceci est important car sans lui, toutes les informations, y compris les mots de passe, sont envoyées sur le réseau en texte brut.

La façon la plus simple d'obtenir un certificat SSL pour sécuriser votre trafic est d'utiliser Let's Encrypt. Suivezthis guide pour configurer Let’s Encrypt avec Nginx sur Ubuntu 16.04.

Conclusion

Dans ce guide, nous avons créé une application Flask simple dans un environnement virtuel Python. Nous créons un point d’entrée WSGI de sorte que tout serveur d’application compatible WSGI puisse s’interfacer avec ce dernier, puis avons configuré le serveur d’applications Gunicorn pour fournir cette fonction. Nous avons ensuite créé un fichier d’unité systemd pour lancer automatiquement le serveur d’applications au démarrage. Nous avons créé un bloc de serveur Nginx qui transmet le trafic du client Web au serveur d'applications en relayant les requêtes externes.

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.