Servieren von Kolbenanwendungen mit Gunicorn und Nginx unter Ubuntu 18.04

Einführung

In diesem Handbuch erstellen Sie eine Python-Anwendung mit dem Flask-Mikroframework unter Ubuntu 18.04. Der Hauptteil dieses Artikels befasst sich mit dem Einrichten vonGunicorn application server und dem Starten der Anwendung sowie dem Konfigurieren vonNginx als Front-End-Reverse-Proxy.

Voraussetzungen

Bevor Sie mit diesem Handbuch beginnen, sollten Sie Folgendes haben:

  • Ein Server mit Ubuntu 18.04 und einem Nicht-Root-Benutzer mit Sudo-Rechten. Befolgen Sie unsereinitial server setup guide als Anleitung.

  • Nginx wird gemäß den Schritten 1 und 2 vonHow To Install Nginx on Ubuntu 18.04 installiert.

  • Ein Domänenname, der so konfiguriert ist, dass er auf Ihren Server verweist. Sie können einen aufNamecheap kaufen oder einen kostenlos aufFreenom erhalten. Sie können lernen, wie Sie Domains auf DigitalOcean verweisen, indem Sie die relevantendocumentation on domains and DNS befolgen. Stellen Sie sicher, dass Sie die folgenden DNS-Einträge erstellen:

    • Ein A-Datensatz mityour_domain, der auf die öffentliche IP-Adresse Ihres Servers verweist.

    • Ein A-Datensatz mitwww.your_domain, der auf die öffentliche IP-Adresse Ihres Servers verweist.

  • Kenntnis der WSGI-Spezifikation, mit der der Gunicorn-Server mit Ihrer Flask-Anwendung kommuniziert. This discussion behandelt WSGI ausführlicher.

[[Schritt 1 - Installieren der Komponenten aus den Ubuntu-Repositorys]] == Schritt 1 - Installieren der Komponenten aus den Ubuntu-Repositorys

Unser erster Schritt wird darin bestehen, alle benötigten Teile aus den Ubuntu-Repositories zu installieren. Dies beinhaltetpip, den Python-Paketmanager, der unsere Python-Komponenten verwaltet. Wir erhalten auch die Python-Entwicklungsdateien, die zum Erstellen einiger Gunicorn-Komponenten erforderlich sind.

Zuerst aktualisieren wir den lokalen Paketindex und installieren die Pakete, mit denen wir unsere Python-Umgebung erstellen können. Dazu gehörenpython3-pip sowie einige weitere Pakete und Entwicklungstools, die für eine robuste Programmierumgebung erforderlich sind:

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

Lassen Sie uns mit diesen Paketen fortfahren und eine virtuelle Umgebung für unser Projekt erstellen.

[[Schritt-2 - Erstellen einer Python-virtuellen Umgebung]] == Schritt 2 - Erstellen einer virtuellen 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 Paketspython3-venv, mit dem das Modulvenv installiert wird:

sudo apt install python3-venv

Als nächstes erstellen wir ein übergeordnetes Verzeichnis für unser Flask-Projekt. Wechseln Sie in das Verzeichnis, nachdem Sie es erstellt haben:

mkdir ~/myproject
cd ~/myproject

Erstellen Sie eine virtuelle Umgebung zum Speichern der Python-Anforderungen Ihres Flask-Projekts, indem Sie Folgendes eingeben:

python3.6 -m venv myprojectenv

Dadurch wird eine lokale Kopie von Python undpip in einem Verzeichnis namensmyprojectenv in Ihrem Projektverzeichnis installiert.

Vor der Installation von Anwendungen in der virtuellen Umgebung müssen Sie diese aktivieren. Geben Sie dazu Folgendes ein:

source myprojectenv/bin/activate

Ihre Eingabeaufforderung ändert sich und zeigt an, dass Sie jetzt in der virtuellen Umgebung arbeiten. Es sieht ungefähr so ​​aus:(myprojectenv)user@host:~/myproject$.

[[Schritt-3 -—- Einrichten einer Kolbenanwendung]] == Schritt 3 - Einrichten einer Kolbenanwendung

Jetzt, da Sie sich in Ihrer virtuellen Umgebung befinden, können Sie Flask und Gunicorn installieren und mit dem Entwerfen Ihrer Anwendung beginnen.

Installieren wir zunächstwheel mit der lokalen Instanz vonpip, um sicherzustellen, dass unsere Pakete auch dann installiert werden, wenn Radarchive fehlen:

pip install wheel

Note

[.note] # Unabhängig davon, welche Python-Version Sie verwenden, sollten Sie bei Aktivierung der virtuellen Umgebung den Befehlpip verwenden (nichtpip3).
#

Als nächstes installieren wir Flask und Gunicorn:

pip install gunicorn flask

Beispiel-App erstellen

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

Während Ihre Anwendung möglicherweise komplexer ist, erstellen wir unsere Flask-App in einer einzigen Datei mit dem Namenmyproject.py:

nano ~/myproject/myproject.py

Der Anwendungscode wird in dieser Datei gespeichert. Es wird Flask importiert und ein Flask-Objekt instanziiert. Hiermit können Sie die Funktionen 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 "

Hello There!

" 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 die Anwendung zu testen, müssen Sie den Zugriff auf Port5000zulassen:

sudo ufw allow 5000

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

python myproject.py

Es wird die folgende Ausgabe angezeigt, einschließlich einer hilfreichen Warnung, die Sie daran erinnert, dieses Server-Setup nicht in der Produktion zu verwenden:

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)

Besuchen Sie die IP-Adresse Ihres Servers, gefolgt von:5000 in Ihrem Webbrowser:

http://your_server_ip:5000

Sie sollten so etwas sehen:

Flask sample app

Wenn Sie fertig sind, drücken SieCTRL-C in Ihrem Terminalfenster, um den Flask-Entwicklungsserver zu stoppen.

Erstellen des WSGI-Einstiegspunkts

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

Nennen wir die Dateiwsgi.py:

nano ~/myproject/wsgi.py

Importieren Sie in dieser Datei die Flask-Instanz aus unserer Anwendung und führen Sie sie dann aus:

~/myproject/wsgi.py

from myproject import app

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

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

[[Schritt-4 - Konfigurieren des Gunicorns]] == Schritt 4 - Konfigurieren des Gunicorns

Ihre Bewerbung wird nun mit einem Einstiegspunkt erstellt. Jetzt können wir mit der Konfiguration von Gunicorn fortfahren.

Bevor wir fortfahren, sollten wir überprüfen, ob Gunicorn die Anwendung korrekt bedienen kann.

Wir können dies tun, indem wir einfach den Namen unseres Einstiegspunkts übergeben. Dies besteht aus dem Namen des Moduls (abzüglich der Erweiterung.py) plus dem Namen des aufrufbaren Moduls in der Anwendung. In unserem Fall ist dieswsgi:app.

Wir geben auch die Schnittstelle und den Port an, an den die Verbindung hergestellt werden soll, damit die Anwendung auf einer öffentlich verfügbaren Schnittstelle gestartet wird:

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

Die Ausgabe sollte folgendermaßen aussehen:

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

Besuchen Sie die IP-Adresse Ihres Servers, wobei:5000in Ihrem Webbrowser erneut an das Ende angehängt ist:

http://your_server_ip:5000

Sie sollten die Ausgabe Ihrer Anwendung sehen:

Flask sample app

Wenn Sie bestätigt haben, dass es ordnungsgemäß funktioniert, drücken SieCTRL-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.

Als nächstes erstellen wir die systemd-Service-Unit-Datei. Durch das Erstellen einer System-Unit-Datei kann Ubuntus Init-System Gunicorn automatisch starten und die Flask-Anwendung bei jedem Start des Servers bedienen.

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

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

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

/etc/systemd/system/myproject.service

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

Als nächstes öffnen wir den Abschnitt[Service]. Dies gibt den Benutzer und die Gruppe an, unter denen der Prozess ausgeführt werden soll. Geben Sie unserem regulären Benutzerkonto den Besitz des Prozesses, da ihm alle relevanten Dateien gehören. Geben wir der Gruppewww-dataauch Gruppenbesitz, damit Nginx problemlos mit den Gunicorn-Prozessen kommunizieren kann. Denken Sie daran, den Benutzernamen hier durch Ihren Benutzernamen zu ersetzen:

/etc/systemd/system/myproject.service

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

[Service]
User=sammy
Group=www-data

Als Nächstes ordnen wir das Arbeitsverzeichnis zu und legen die UmgebungsvariablePATHfest, damit das Init-System weiß, dass sich die ausführbaren Dateien für den Prozess in unserer virtuellen Umgebung befinden. Geben Sie auch den Befehl zum Starten des Dienstes an. Dieser Befehl führt Folgendes aus:

  • Starten Sie 3 Worker-Prozesse (obwohl Sie dies nach Bedarf anpassen sollten)

  • Erstellen und binden Sie eine Unix-Socket-Dateimyproject.sock in unserem Projektverzeichnis. Wir setzen einen umask-Wert von007, damit die Socket-Datei erstellt wird, die den Zugriff auf den Eigentümer und die Gruppe ermöglicht, während der andere Zugriff eingeschränkt wird

  • Geben Sie den Namen der WSGI-Einstiegspunktdatei zusammen mit dem in dieser Datei aufrufbaren Python an (wsgi:app).

Systemd erfordert, dass wir den vollständigen Pfad zur ausführbaren Datei von Gunicorn angeben, die in unserer virtuellen Umgebung installiert ist.

Denken Sie daran, den Benutzernamen und die Projektpfade durch Ihre eigenen Informationen zu ersetzen:

/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

Zum Schluss 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=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

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

Wir können jetzt den von uns erstellten Gunicorn-Dienst starten und aktivieren, sodass er beim Booten startet:

sudo systemctl start myproject
sudo systemctl enable myproject

Überprüfen wir den Status:

sudo systemctl status myproject

Sie sollten die Ausgabe so sehen:

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

Wenn Fehler auftreten, müssen Sie diese beheben, bevor Sie mit dem Lernprogramm fortfahren.

[[Schritt-5 - Konfigurieren von Nginx-zu-Proxy-Anforderungen]] == Schritt 5 - Konfigurieren von Nginx zu Proxy-Anforderungen

Unser Gunicorn-Anwendungsserver sollte nun betriebsbereit sein und auf Anforderungen in der Socket-Datei im Projektverzeichnis warten. Lassen Sie uns nun Nginx so konfigurieren, dass Webanforderungen an diesen Socket weitergeleitet werden, indem Sie einige kleine Änderungen an der Konfigurationsdatei vornehmen.

Beginnen Sie mit der Erstellung einer neuen Serverblock-Konfigurationsdatei imsites-available-Verzeichnis von Nginx. Nennen wir diesemyproject, um mit dem Rest des Handbuchs Schritt zu halten:

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

Öffnen Sie einen Serverblock und weisen Sie Nginx an, den Standardport80 abzuhören. Sagen wir ihm auch, dass er diesen Block für Anfragen nach dem Domain-Namen unseres Servers verwenden soll:

/etc/nginx/sites-available/myproject

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

Als nächstes fügen wir einen Standortblock hinzu, der zu jeder Anfrage passt. In diesem Block enthalten wir die Dateiproxy_params, in der einige allgemeine Proxy-Parameter angegeben sind, die festgelegt werden müssen. Anschließend übergeben wir die Anforderungen an den Socket, den wir mit der Direktiveproxy_passdefiniert haben:

/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;
    }
}

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

Verknüpfen Sie die Datei mit dem Verzeichnissites-enabled, um die soeben erstellte Nginx-Serverblockkonfiguration zu aktivieren:

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

Mit der Datei in diesem Verzeichnis können Sie nach Syntaxfehlern suchen:

sudo nginx -t

Wenn dies ohne Hinweis auf ein Problem erneut auftritt, starten Sie den Nginx-Prozess neu, um die neue Konfiguration zu lesen:

sudo systemctl restart nginx

Passen wir zum Schluss die Firewall erneut an. Wir brauchen keinen Zugriff mehr über Port5000, daher können wir diese Regel entfernen. Wir können dann den vollen Zugriff auf den Nginx-Server erlauben:

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

Sie sollten nun in der Lage sein, in Ihrem Webbrowser zum Domainnamen Ihres Servers zu navigieren:

http://your_domain

Sie sollten die Ausgabe Ihrer Anwendung sehen:

Flask sample app

Wenn Sie auf Fehler stoßen, überprüfen Sie Folgendes:

  • sudo less /var/log/nginx/error.log: Überprüft die Nginx-Fehlerprotokolle.

  • sudo less /var/log/nginx/access.log: Überprüft die Nginx-Zugriffsprotokolle.

  • sudo journalctl -u nginx: Überprüft die Nginx-Prozessprotokolle.

  • sudo journalctl -u myproject: Überprüft die Gunicorn-Protokolle Ihrer Flask-App.

[[Schritt-6 - Sichern der Anwendung]] == Schritt 6 - Sichern der Anwendung

Um sicherzustellen, dass der Datenverkehr zu Ihrem Server sicher bleibt, fordern wir ein SSL-Zertifikat für Ihre Domain an. Es gibt mehrere Möglichkeiten, dies zu tun, einschließlich des Abrufs eines kostenlosen Zertifikats vonLet’s Encrypt,generating a self-signed certificate oderbuying one from another provider und der Konfiguration von Nginx für die Verwendung, indem Sie die Schritte 2 bis 6 vonHow to Create a Self-signed SSL Certificate for Nginx in Ubuntu 18.04 ausführen . Wir werden aus Gründen der Zweckmäßigkeit die erste Option wählen.

Fügen Sie zunächst das Certbot Ubuntu-Repository hinzu:

sudo add-apt-repository ppa:certbot/certbot

Sie müssenENTER drücken, um zu akzeptieren.

Installieren Sie das Nginx-Paket von Certbot mitapt:

sudo apt install python-certbot-nginx

Certbot bietet verschiedene Möglichkeiten, SSL-Zertifikate über Plugins abzurufen. Das Nginx-Plugin kümmert sich darum, Nginx neu zu konfigurieren und die Konfiguration bei Bedarf neu zu laden. Geben Sie Folgendes ein, um dieses Plugin zu verwenden:

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

Dadurch wirdcertbot mit dem Plugin--nginx ausgeführt, wobei-d verwendet wird, um die Namen anzugeben, für die das Zertifikat gültig sein soll.

Wenn Siecertbot zum ersten Mal ausführen, werden Sie aufgefordert, eine E-Mail-Adresse einzugeben und den Nutzungsbedingungen zuzustimmen. Danach kommuniziertcertbot mit dem Let's Encrypt-Server und führt dann eine Herausforderung aus, um zu überprüfen, ob Sie die Domäne steuern, für die Sie ein Zertifikat anfordern.

Wenn dies erfolgreich ist, werden Sie voncertbotgefragt, wie Sie Ihre HTTPS-Einstellungen konfigurieren möchten:

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):

Wählen Sie Ihre Wahl und drücken SieENTER. Die Konfiguration wird aktualisiert und Nginx wird neu geladen, um die neuen Einstellungen zu übernehmen. certbot wird mit einer Nachricht abgeschlossen, die Ihnen mitteilt, dass der Prozess erfolgreich war und wo Ihre Zertifikate gespeichert sind:

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

Wenn Sie die Nginx-Installationsanweisungen in den Voraussetzungen befolgt haben, benötigen Sie nicht mehr die redundante HTTP-Profilerlaubnis:

sudo ufw delete allow 'Nginx HTTP'

Navigieren Sie zum Überprüfen der Konfiguration erneut mithttps:// zu Ihrer Domain:

https://your_domain

Sie sollten Ihre Anwendungsausgabe erneut sehen, zusammen mit der Sicherheitsanzeige Ihres Browsers, die darauf hinweist, dass die Site gesichert ist.

Fazit

In diesem Handbuch haben Sie eine einfache Flask-Anwendung in einer virtuellen Python-Umgebung erstellt und gesichert. Sie haben einen WSGI-Einstiegspunkt erstellt, damit jeder WSGI-fähige Anwendungsserver mit ihm kommunizieren kann, und dann den Gunicorn-App-Server so konfiguriert, dass er diese Funktion bereitstellt. Anschließend haben Sie eine systemd-Servicedatei erstellt, um den Anwendungsserver beim Booten automatisch zu starten. Sie haben auch einen Nginx-Serverblock erstellt, der den Webclient-Datenverkehr an den Anwendungsserver weiterleitet, externe Anforderungen weiterleitet und den Datenverkehr mit Let's Encrypt an Ihren Server sichert.

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.