Serving von Flask-Anwendungen mit uWSGI und Nginx unter Ubuntu 16.04

Einführung

In diesem Handbuch richten wir eine einfache Python-Anwendung mit dem Flask-Micro-Framework unter Ubuntu 16.04 ein. Der Großteil dieses Artikels befasst sich mit der Einrichtung des uWSGI-Anwendungsservers zum Starten der Anwendung und von Nginx als Front-End-Reverse-Proxy.

Voraussetzungen

Bevor Sie mit diesem Handbuch beginnen, sollte auf Ihrem Server ein Benutzer ohne Rootberechtigung konfiguriert sein. Dieser Benutzer benötigt die Berechtigung "+ sudo +", um administrative Funktionen ausführen zu können. Informationen zum Einrichten finden Sie in unserem initial server setup guide.

Weitere Informationen zu uWSGI, unserem Anwendungsserver und der WSGI-Spezifikation finden Sie im verlinkten Abschnitt unter https://www.digitalocean.com/community/tutorials/how-to-set-up-uwsgi-and-nginx-to -serve-python-apps-on-ubuntu-14-04 # definitionen-und-konzepte [dieses handbuch]. Das Verständnis dieser Konzepte erleichtert das Befolgen dieser Anleitung.

Wenn Sie bereit sind fortzufahren, lesen Sie weiter.

Installieren Sie die Komponenten aus den Ubuntu-Repositories

Unser erster Schritt wird sein, alle Teile, die wir brauchen, aus den Repositories zu installieren. Wir werden + pip +, den Python-Paketmanager, installieren, um unsere Python-Komponenten zu installieren und zu verwalten. Wir werden auch die Python-Entwicklungsdateien erhalten, die zum Erstellen von uWSGI benötigt werden, und wir werden jetzt auch Nginx installieren.

Wir müssen den lokalen Paketindex aktualisieren und dann die Pakete installieren. Welche Pakete Sie benötigen, hängt davon ab, ob Ihr Projekt Python 2 oder Python 3 verwendet.

Wenn Sie * Python 2 * verwenden, geben Sie Folgendes ein:

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

Wenn Sie stattdessen * Python 3 * verwenden, geben Sie Folgendes ein:

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

Erstellen Sie eine virtuelle Python-Umgebung

Als Nächstes richten wir eine virtuelle Umgebung ein, um unsere Flask-Anwendung von den anderen Python-Dateien auf dem System zu isolieren.

Beginnen Sie mit der Installation des Pakets "+ virtualenv" mit "+ pip".

Wenn Sie * Python 2 * verwenden, geben Sie Folgendes ein:

sudo pip install virtualenv

Wenn Sie * Python 3 * verwenden, geben Sie Folgendes ein:

sudo pip3 install virtualenv

Jetzt können wir ein übergeordnetes Verzeichnis für unser Flask-Projekt erstellen. Wechseln Sie in das Verzeichnis, nachdem Sie es erstellt haben:

mkdir ~/
cd ~/

Wir können eine virtuelle Umgebung zum Speichern der Python-Anforderungen unseres Flask-Projekts erstellen, indem Sie Folgendes eingeben:

virtualenv

Dies installiert eine lokale Kopie von Python und "+ pip " in ein Verzeichnis mit dem Namen "+" in Ihrem Projektverzeichnis.

Bevor wir Anwendungen in der virtuellen Umgebung installieren, müssen wir sie aktivieren. Sie können dies tun, indem Sie Folgendes eingeben:

source /bin/activate

Ihre Eingabeaufforderung ändert sich und zeigt an, dass Sie jetzt in der virtuellen Umgebung arbeiten. Es wird ungefähr so ​​aussehen: + () @: ~ / $ +.

Einrichten einer Kolbenanwendung

Jetzt, da Sie sich in Ihrer virtuellen Umgebung befinden, können wir Flask und uWSGI installieren und mit dem Entwerfen unserer Anwendung beginnen:

Installieren Sie Flask und uWSGI

Wir können die lokale Instanz von "+ pip +" verwenden, um Flask und uWSGI zu installieren. Geben Sie die folgenden Befehle ein, um diese beiden Komponenten abzurufen:

Note

pip install uwsgi flask

Erstellen Sie eine Beispiel-App

Nachdem wir Flask zur Verfügung haben, können wir eine einfache Anwendung erstellen. Der Kolben ist ein Mikrorahmen. Es enthält nicht viele der Tools, die für umfassendere Frameworks geeignet sind, und ist hauptsächlich als Modul verfügbar, das Sie in Ihre Projekte importieren können, um Sie bei der Initialisierung einer Webanwendung zu unterstützen.

Auch wenn Ihre Anwendung komplexer sein mag, erstellen wir unsere Flask-App in einer einzigen Datei, die wir als "+ myproject.py +" bezeichnen:

nano ~//.py

In dieser Datei platzieren wir unseren Anwendungscode. Grundsätzlich müssen wir Flask importieren und ein Flask-Objekt instanziieren. Wir können dies verwenden, um die Funktionen zu definieren, die ausgeführt werden sollen, wenn eine bestimmte Route angefordert wird:

~ / myproject / myproject.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
   return "<h1 style='color:blue'>Hello There!</h1>"

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

Dies definiert im Wesentlichen, welcher Inhalt angezeigt wird, wenn auf die Stammdomäne zugegriffen wird. Speichern und schließen Sie die Datei, wenn Sie fertig sind.

Wenn Sie die anfängliche Anleitung zur Serverkonfiguration befolgt haben, sollte eine UFW-Firewall aktiviert sein. Um unsere Anwendung zu testen, müssen wir den Zugriff auf Port 5000 zulassen.

Öffnen Sie Port 5000, indem Sie Folgendes eingeben:

sudo ufw allow 5000

Jetzt können Sie Ihre Flask-App testen, indem Sie Folgendes eingeben:

python .py

Besuchen Sie den Domainnamen oder die IP-Adresse Ihres Servers, gefolgt von "+: 5000 +" in Ihrem Webbrowser:

http://:5000

Sie sollten so etwas sehen:

image: https: //assets.digitalocean.com/articles/nginx_uwsgi_wsgi_1404/test_app.png [Flask sample app]

Wenn Sie fertig sind, drücken Sie einige Male STRG-C im Terminalfenster, um den Flask-Entwicklungsserver zu stoppen.

Erstellen Sie den WSGI-Einstiegspunkt

Als Nächstes erstellen wir eine Datei, die als Einstiegspunkt für unsere Anwendung dient. Dies teilt unserem uWSGI-Server mit, wie er mit der Anwendung interagieren soll.

Wir werden die Datei + wsgi.py + aufrufen:

nano ~//wsgi.py

Die Datei ist unglaublich einfach. Wir können einfach die Flask-Instanz aus unserer Anwendung importieren und dann ausführen:

~ / myproject / wsgi.py

from myproject import app

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

Speichern und schließen Sie die Datei, wenn Sie fertig sind.

Konfigurieren Sie uWSGI

Unsere Bewerbung ist nun geschrieben und unser Einstiegspunkt festgelegt. Wir können jetzt zu uWSGI übergehen.

Testen von uWSGI-Serving

Als Erstes testen wir, ob uWSGI für unsere Anwendung geeignet ist.

Wir können dies tun, indem wir einfach den Namen unseres Einstiegspunkts übergeben. Dies setzt sich aus dem Namen des Moduls (wie üblich abzüglich der Erweiterung "+ .py ") und dem Namen des aufrufbaren Elements in der Anwendung zusammen. In unserem Fall wäre dies " wsgi: app +".

Wir geben außerdem den Socket an, damit er auf einer öffentlich zugänglichen Schnittstelle gestartet wird, und das Protokoll, damit HTTP anstelle des Binärprotokolls "+ uwsgi +" verwendet wird. Wir werden die gleiche Portnummer verwenden, die wir zuvor geöffnet haben:

uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app

Rufen Sie den Domain-Namen oder die IP-Adresse Ihres Servers auf, und fügen Sie "+: 5000 +" in Ihrem Webbrowser erneut an das Ende an:

http://:5000

Sie sollten die Ausgabe Ihrer Anwendung erneut sehen:

image: https: //assets.digitalocean.com/articles/nginx_uwsgi_wsgi_1404/test_app.png [Flask sample app]

Wenn Sie die ordnungsgemäße Funktion bestätigt haben, drücken Sie STRG-C in Ihrem Terminalfenster.

Wir sind jetzt mit unserer virtuellen Umgebung fertig und können sie deaktivieren:

deactivate

Alle Python-Befehle verwenden jetzt wieder die Python-Umgebung des Systems.

Erstellen einer uWSGI-Konfigurationsdatei

Wir haben getestet, dass uWSGI in der Lage ist, unsere Anwendung zu bedienen, aber wir möchten etwas Robusteres für die langfristige Nutzung. Wir können eine uWSGI-Konfigurationsdatei mit den gewünschten Optionen erstellen.

Fügen Sie das in unser Projektverzeichnis ein und nennen Sie es "+ myproject.ini +":

nano ~//.ini

Im Inneren beginnen wir mit dem Header "+ [uwsgi] ", damit uWSGI die Einstellungen anwenden kann. Wir geben das Modul an, indem wir uns auf unsere Datei " wsgi.py +" beziehen, abzüglich der Erweiterung, und dass das aufrufbare Element in der Datei "app" heißt:

~ / myproject / myproject.ini

[uwsgi]
module = wsgi:app

Als Nächstes weisen wir uWSGI an, im Mastermodus zu starten und fünf Arbeitsprozesse zu erzeugen, um die tatsächlichen Anforderungen zu erfüllen:

~ / myproject / myproject.ini

[uwsgi]
module = wsgi:app

master = true
processes = 5

Beim Testen haben wir uWSGI auf einem Netzwerkport verfügbar gemacht. Wir werden jedoch Nginx verwenden, um die tatsächlichen Clientverbindungen zu verarbeiten, die dann Anforderungen an uWSGI weiterleiten. Da diese Komponenten auf demselben Computer ausgeführt werden, wird ein Unix-Socket bevorzugt, da er sicherer und schneller ist. Wir rufen den Socket "+ myproject.sock +" auf und platzieren ihn in diesem Verzeichnis.

Wir müssen auch die Berechtigungen für den Socket ändern. Wir geben der Nginx-Gruppe später den Besitz des uWSGI-Prozesses. Daher müssen wir sicherstellen, dass der Gruppeneigentümer des Sockets Informationen von ihm lesen und in ihn schreiben kann. Wir werden auch den Sockel bereinigen, wenn der Prozess anhält, indem wir die Option "Vakuum" hinzufügen:

~ / myproject / myproject.ini

[uwsgi]
module = wsgi:app

master = true
processes = 5

socket = .sock
chmod-socket = 660
vacuum = true

Das Letzte, was wir tun müssen, ist die Option + die-on-term + zu setzen. Dies kann dazu beitragen, dass das Init-System und uWSGI dieselben Annahmen über die Bedeutung der einzelnen Prozesssignale haben. Durch diese Einstellung werden die beiden Systemkomponenten ausgerichtet und das erwartete Verhalten implementiert:

~ / myproject / myproject.ini

[uwsgi]
module = wsgi:app

master = true
processes = 5

socket = .sock
chmod-socket = 660
vacuum = true

die-on-term = true

Möglicherweise haben Sie bemerkt, dass wir kein Protokoll wie in der Befehlszeile angegeben haben. Dies liegt daran, dass uWSGI standardmäßig das "+ uwsgi +" - Protokoll verwendet, ein schnelles Binärprotokoll, das für die Kommunikation mit anderen Servern entwickelt wurde. Nginx kann dieses Protokoll nativ sprechen, daher ist es besser, dies zu verwenden, als die Kommunikation über HTTP zu erzwingen.

Wenn Sie fertig sind, speichern und schließen Sie die Datei.

Erstellen Sie eine systemd Unit-Datei

Das nächste Stück, um das wir uns kümmern müssen, ist die systemd-Service-Unit-Datei. Durch das Erstellen einer System-Unit-Datei kann Ubuntus Init-System uWSGI automatisch starten und unsere Flask-Anwendung beim Booten des Servers bereitstellen.

Erstellen Sie eine Unit-Datei mit der Endung .service im Verzeichnis / etc / systemd / system, um zu beginnen:

sudo nano /etc/systemd/system/.service

Im Inneren beginnen wir mit dem Abschnitt "+ [Unit] +", in dem Metadaten und Abhängigkeiten angegeben werden. Wir werden hier eine Beschreibung unseres Dienstes einfügen und das init-System anweisen, diese erst zu starten, nachdem das Netzwerkziel erreicht wurde:

/etc/systemd/system/myproject.service

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

Als nächstes öffnen wir den Abschnitt "+ [Service] ". Wir geben den Benutzer und die Gruppe an, unter denen der Prozess ausgeführt werden soll. Wir geben unserem regulären Benutzerkonto den Besitz des Prozesses, da ihm alle relevanten Dateien gehören. Damit Nginx problemlos mit den uWSGI-Prozessen kommunizieren kann, geben wir der Gruppe " www-data" den Gruppeneigentum.

Anschließend ordnen wir das Arbeitsverzeichnis zu und setzen die Umgebungsvariable "+ PATH +", damit das Init-System weiß, wo sich die ausführbaren Dateien für den Prozess befinden (in unserer virtuellen Umgebung). Anschließend geben wir den Befehl zum Starten des Dienstes an. Systemd erfordert, dass wir den vollständigen Pfad zur ausführbaren uWSGI-Datei angeben, die in unserer virtuellen Umgebung installiert ist. Wir übergeben den Namen der INI-Konfigurationsdatei, die wir in unserem Projektverzeichnis erstellt haben:

/etc/systemd/system/myproject.service

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

[Service]
User=
Group=www-data
WorkingDirectory=/home//
Environment="PATH=/home////bin"
ExecStart=/home////bin/uwsgi --ini .ini

Schließlich fügen wir einen Abschnitt "+ [Install] +" hinzu. Dies teilt systemd mit, mit was dieser Dienst verknüpft werden soll, wenn er beim Booten gestartet werden kann. Wir möchten, dass dieser Dienst gestartet wird, wenn das reguläre Mehrbenutzersystem ausgeführt wird:

/etc/systemd/system/myproject.service

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

[Service]
User=
Group=www-data
WorkingDirectory=/home//
Environment="PATH=/home////bin"
ExecStart=/home////bin/uwsgi --ini .ini

[Install]
WantedBy=multi-user.target

Damit ist unsere systemd-Servicedatei vollständig. Speichern und schließen Sie es jetzt.

Jetzt können wir den von uns erstellten uWSGI-Dienst starten und aktivieren, sodass er beim Booten startet:

sudo systemctl start
sudo systemctl enable

Konfigurieren von Nginx für Proxy-Anforderungen

Unser uWSGI-Anwendungsserver sollte nun betriebsbereit sein und auf Anforderungen in der Socket-Datei im Projektverzeichnis warten. Wir müssen Nginx so konfigurieren, dass Webanforderungen mit dem Protokoll "+ uwsgi +" an diesen Socket weitergeleitet werden.

Beginnen Sie mit der Erstellung einer neuen Serverblock-Konfigurationsdatei im Verzeichnis "+ sites-available " von Nginx. Wir rufen einfach " myproject +" auf, um mit dem Rest des Handbuchs Schritt zu halten:

sudo nano /etc/nginx/sites-available/

Öffnen Sie einen Serverblock und weisen Sie Nginx an, den Standardport 80 abzuhören. Wir müssen es auch anweisen, diesen Block für Anfragen nach dem Domainnamen oder der IP-Adresse unseres Servers zu verwenden:

/ etc / nginx / sites-available / myproject

server {
   listen 80;
   server_name ;
}

Das einzige andere, was wir hinzufügen müssen, ist ein Standortblock, der zu jeder Anfrage passt. In diesem Block wird die Datei "+ uwsgi_params " eingefügt, die einige allgemeine uWSGI-Parameter angibt, die festgelegt werden müssen. Anschließend leiten wir die Anforderungen an den Socket weiter, den wir mit der Direktive " uwsgi_pass +" definiert haben:

/ etc / nginx / sites-available / myproject

server {
   listen 80;
   server_name ;

   location / {
       include uwsgi_params;
       uwsgi_pass unix:/home///.sock;
   }
}

Das ist eigentlich alles, was wir für unsere Anwendung benötigen. Speichern und schließen Sie die Datei, wenn Sie fertig sind.

Um die soeben erstellte Nginx-Serverblockkonfiguration zu aktivieren, verknüpfen Sie die Datei mit dem Verzeichnis "+ sites-enabled +":

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

Mit der Datei in diesem Verzeichnis können wir nach Syntaxfehlern suchen, indem wir Folgendes eingeben:

sudo nginx -t

Wenn dies ohne Anzeichen von Problemen zurückkommt, können wir den Nginx-Prozess neu starten, um die neue Konfiguration zu lesen:

sudo systemctl restart nginx

Als letztes müssen wir unsere Firewall erneut anpassen. Wir brauchen keinen Zugriff mehr über Port 5000, daher können wir diese Regel entfernen. Wir können dann den Zugriff auf den Nginx-Server erlauben:

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

Sie sollten nun in Ihrem Webbrowser auf den Domainnamen oder die IP-Adresse Ihres Servers zugreifen können:

http://

Sie sollten Ihre Anwendungsausgabe sehen:

image: https: //assets.digitalocean.com/articles/nginx_uwsgi_wsgi_1404/test_app.png [Flask sample app]

Note

Fazit

In diesem Handbuch haben wir eine einfache Flask-Anwendung in einer virtuellen Python-Umgebung erstellt. Wir erstellen einen WSGI-Einstiegspunkt, damit jeder WSGI-fähige Anwendungsserver mit ihm kommunizieren kann, und konfigurieren dann den uWSGI-Anwendungsserver so, dass er diese Funktion bereitstellt. Anschließend haben wir eine systemd-Servicedatei erstellt, um den Anwendungsserver beim Booten automatisch zu starten. Wir haben einen Nginx-Serverblock erstellt, der den Webclient-Datenverkehr an den Anwendungsserver weiterleitet und externe Anforderungen weiterleitet.

Flask ist ein sehr einfaches, aber äußerst flexibles Framework, mit dem Sie Ihre Anwendungen mit Funktionen versehen können, ohne die Struktur und das Design zu stark einzuschränken. Mit dem in diesem Handbuch beschriebenen allgemeinen Stapel können Sie die von Ihnen entworfenen Kolbenanwendungen bedienen.