In diesem Leitfaden erstellen Sie eine Python-Anwendung mithilfe des Flask-Microframeworks unter Ubuntu 20.04. Im Großteil dieses Artikels geht es um die Einrichtung des Gunicorn Anwendungsservers und das Starten der Anwendung sowie um die Konfiguration von Nginx als Front-end-Reverse-Proxy.
Bevor Sie mit diesem Leitfaden beginnen, sollten Sie folgende Voraussetzungen erfüllt haben:
Einen Server mit installiertem Ubuntu 20.04 und Nicht-root-Benutzer mit sudo-Berechtigungen. Folgen Sie als Orientierung unserem Leitfaden zur Ersteinrichtung des Servers.
Wenn Nginx installiert ist, folgen Sie den Schritten 1 und 2 in Installieren von Nginx unter Ubuntu 20.04.
Einen Domänennamen, der so konfiguriert ist, dass er auf Ihren Server verweist. Sie können einen Domänennamen bei Namecheap kaufen bzw. kostenlos bei Freenom erhalten. In der entsprechenden Dokumentation zu Domänen und DNS erfahren Sie, wie Sie Domänen auf DigitalOcean verweisen. Sie müssen folgende DNS-Einträge erstellen:
your-domain
, der auf die öffentliche IP-Adresse Ihres Servers verweist.your-domain
, der auf die öffentliche IP-Adresse Ihres Servers verweist.Vertrautheit mit der WSGI-Spezifikation, die der Gunicorn Server zur Kommunikation mit Ihrer Flask-Anwendung nutzt. In dieser Erläuterung wird WSGI näher besprochen.
Unser erster Schritt besteht darin, alle Elemente zu installieren, die aus den Ubuntu-Repositorys benötigt werden. Dazu gehört pip
, der Python-Paketmanager, der unsere Python-Komponenten verwalten wird. Außerdem erhalten wir die zum Erstellen einiger Gunicorn-Komponenten benötigten Python-Entwicklungsdateien.
Wir aktualisieren zuerst den lokalen Paketindex und installieren die Pakete, mit denen wir unsere Python-Umgebung aufbauen können. Dazu gehören python3-pip
sowie einige weitere Pakete und Entwicklungs-Tools, 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
Wenn diese Pakete eingerichtet sind, fahren wir mit der Erstellung einer virtuellen Umgebung für unser Projekt fort.
Als Nächstes richten wir eine virtuelle Umgebung ein, um unsere Flask-Anwendung von anderen Python-Dateien auf dem System zu isolieren.
Beginnen Sie mit der Installation des python3-venv
Pakets, womit das venv
Modul installiert wird:
- sudo apt install python3-venv
Als Nächstes erstellen wir ein übergeordnetes Verzeichnis für unser Flask-Projekt. Nachdem Sie es erstellt haben, wechseln Sie in das Verzeichnis:
- mkdir ~/myproject
- cd ~/myproject
Erstellen Sie eine virtuelle Umgebung, um die Python-Anforderungen Ihres Flask-Projekts zu speichern, indem Sie Folgendes eingeben:
- python3 -m venv myprojectenv
Auf diese Weise wird eine lokale Kopie von Python und pip
in ein Verzeichnis mit dem Namen myprojectenv
innerhalb Ihres Projektverzeichnisses installiert.
Bevor Sie Anwendungen innerhalb der virtuellen Umgebung installieren, müssen Sie sie aktivieren. Geben Sie hierfür Folgendes ein:
- source myprojectenv/bin/activate
Ihre Eingabeaufforderung ändert sich und zeigt an, dass Sie jetzt innerhalb der virtuellen Umgebung arbeiten. Sie sieht etwa wie folgt aus: (myprojectenv)user@host:~/myproject$
.
Sie befinden sich nun in Ihrer virtuellen Umgebung und können somit Flask und Gunicorn installieren und mit der Gestaltung Ihrer Anwendung beginnen.
Wir installieren zuerst wheel
mit der lokalen Instanz von pip
, um sicherzustellen, dass unsere Pakete installiert werden, selbst wenn wheel-Archive fehlen:
- pip install wheel
Hinweis
Unabhängig davon, welche Version von Python Sie verwenden, wenn die virtuelle Umgebung aktiviert ist, sollten Sie den Befehl pip
(nicht pip3
) verwenden.
Als Nächstes installieren wir Flask und Gunicorn:
- pip install gunicorn flask
Nachdem Sie jetzt über Flask verfügen, können Sie eine einfache Anwendung erstellen. Flask ist ein Microframework. Es enthält nicht viele der Tools, die vollwertige Frameworks möglicherweise ausmachen, und besteht hauptsächlich als Modul, 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 Namen myproject.py
:
- nano ~/myproject/myproject.py
Der Anwendungscode ist in dieser Datei enthalten. Er importiert Flask und instanziiert ein Flask-Objekt. Sie können damit die Funktionen definieren, die nach der Anfrage einer bestimmten Route ausgeführt werden sollen:
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, welche Inhalte beim Zugriff auf die Stammdomäne gezeigt werden. Speichern und schließen Sie abschließend die Datei.
Wenn Sie den Leitfaden zur Servereinrichtung befolgt haben, sollte Ihre UFW-Firewall aktiviert sein. Um die Anwendung zu testen, müssen Sie den Zugriff auf Port 5000
zulassen:
- sudo ufw allow 5000
Geben Sie Folgendes ein, um Ihre Flask-App zu testen:
- python myproject.py
Sie sehen eine Ausgabe ähnlich wie die Folgende mit einer praktischen Warnung, die Sie darauf hinweist, diese Servereinrichtung nicht produktiv zu nutzen:
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)
Gehen Sie auf die IP-Adresse Ihres Servers, gefolgt von :5000
in Ihrem Webbrowser:
http://your_server_ip:5000
Sie sollten in etwa Folgendes sehen:
Wenn Sie fertig sind, betätigen Sie STRG-C
in Ihrem Terminalfenster, um den Flask-Entwicklungsserver anzuhalten.
Als Nächstes erstellen wir eine Datei, die als Einstiegspunkt für unsere Anwendung dient. Diese sagt dem Gunicorn-Server, wie die Interaktion mit der Anwendung erfolgt.
Wir wollen die Datei wsgi.py
nennen:
- nano ~/myproject/wsgi.py
In diese Datei importieren wir die Flask-Instanz aus unserer Anwendung und führen sie dann aus:
from myproject import app
if __name__ == "__main__":
app.run()
Wenn Sie fertig sind, speichern und schließen Sie die Datei.
Ihre Anwendung ist jetzt mit einem bestehenden Einstiegspunkt geschrieben. Wir können jetzt mit der Konfiguration von Gunicorn fortfahren.
Bevor wir fortfahren, sollten wir überprüfen, ob Gunicorn die Anwendung korrekt bedienen kann.
Dazu geben wir einfach den Namen des Einstiegspunktes weiter. Dieser ist als der Name des Moduls (minus die Erweiterung .py
) plus der Name des Callable innerhalb der Anwendung aufgebaut. In unserem Fall ist das wsgi:app
.
Außerdem geben wir die Schnittstelle und den Port an, damit die Anwendung auf einer öffentlich verfügbaren Schnittstelle gestartet wird:
- cd ~/myproject
- gunicorn --bind 0.0.0.0:5000 wsgi:app
Sie sollten eine Ausgabe wie die folgende sehen:
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
Gehen Sie auf die IP-Adresse Ihres Servers mit :5000
, das am Ende Ihres Webbrowsers erneut angehängt ist:
http://your_server_ip:5000
Sie sollten die Ausgabe Ihrer Anwendung sehen:
Wenn Sie die ordnungsgemäße Funktionsweise bestätigt haben, betätigen Sie STRG-C
in Ihrem Terminalfenster.
Wir sind jetzt mit unserer virtuellen Umgebung fertig und können sie deaktivieren:
- deactivate
Alle Python-Befehle nutzen jetzt wieder die Python-Umgebung des Systems.
Als Nächstes erstellen wir die systemd-Diensteinheit-Datei. Das Erstellen einer systemd Unit-Datei ermöglicht, dass das Init-System von Ubuntu Gunicorn automatisch startet und die Flask-Anwendung bei jedem Hochfahren des Servers bedient wird.
Erstellen Sie zunächst eine Unit-Datei, die auf .service
endet, innerhalb des Verzeichnisses /etc/systemd/system
:
- sudo nano /etc/systemd/system/myproject.service
Darin beginnen wir mit dem Abschnitt [Unit]
, mit dem Metadaten und Abhängigkeiten angegeben werden. Wir wollen hier eine Beschreibung unseres Dienstes eingeben und dem Init-System mitteilen, ihn nur zu starten, nachdem das Netzwerkziel erreicht wurde:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
Als Nächstes wollen wir den Abschnitt [Service]
öffnen. Damit werden der Benutzer und die Gruppe angegeben, unter denen wir den Prozess ausführen möchten. Wir wollen unserem regulären Benutzerkonto die Prozessverantwortung übergeben, da es alle relevanten Dateien besitzt. Wir wollen außerdem der Gruppe www-data
die Gruppenverantwortung übertragen, damit Nginx einfach mit den Gunicorn-Prozessen kommunizieren kann. Denken Sie daran, den Benutzername hier durch Ihren Benutzernamen zu ersetzen:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
Als Nächstes wollen wir das Arbeitsverzeichnis darstellen und die Umgebungsvariable PATH
setzen, damit das Init-System weiß, dass sich die ausführbaren Daten für den Prozess innerhalb unserer virtuellen Umgebung befinden. Wir wollen auch den Befehl zum Starten des Dienstes angeben. Dieser Befehl führt Folgendes aus:
myproject.sock
Unix Socket-Datei, innerhalb unseres Projektverzeichnisses. Wir setzen einen umask-Wert von 007
ein, um die Socket-Datei zu erstellen, die den Zugriff auf den Eigentümer und die Gruppe erteilt, aber den Zugriff anderer einschränkt.wsgi:app
) an.Systemd erfordert, dass wir der ausführbaren Gunicorn den vollen Pfad geben, der innerhalb unserer virtuellen Umgebung installiert ist.
Denken Sie daran, den Benutzernamen und die Projektpfade durch Ihre eigenen Informationen zu ersetzen:
[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
Schließlich fügen wir einen [Install]
-Abschnitt hinzu. Dies teilt systemd mit, womit dieser Dienst verknüpft werden soll, wenn wir festlegen, dass er während des Startvorgangs starten soll. Wir wollen, dass dieser Dienst startet, wenn das normale Mehrbenutzersystem arbeitet.
[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-Dienstdatei fertiggestellt. Speichern und schließen Sie diese jetzt.
Wir können nun den Gunicorn-Dienst starten, den wir erstellt haben, und festlegen, dass er während des Startvorgangs startet:
- sudo systemctl start myproject
- sudo systemctl enable myproject
Wir wollen den Status überprüfen:
- sudo systemctl status myproject
Sie sollten eine Ausgabe wie diese sehen:
Output● myproject.service - Gunicorn instance to serve myproject
Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2020-05-20 14:15:18 UTC; 1s ago
Main PID: 46430 (gunicorn)
Tasks: 4 (limit: 2344)
Memory: 51.3M
CGroup: /system.slice/myproject.service
├─46430 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─46449 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─46450 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
└─46451 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
Wenn Sie Fehler sehen, müssen Sie sie beheben, bevor Sie mit dem Tutorial fortfahren.
Unser Gunicorn-Anwendungsserver sollte nun ausgeführt werden und darauf warten, dass Anfragen an die Socket-Datei im Projektverzeichnis gestellt werden. Wir wollen nun konfigurieren, dass Nginx Webanfragen an diesen Socket übergibt, indem wir einige kleine Ergänzungen zu dieser Konfigurationsdatei hinzufügen.
Beginnen Sie mit der Erstellung einer neuen Serverblockkonfigurationsdatei im Nginx-Verzeichnis sites-available
. Wir wollen es myproject
nennen, um die Einheitlichkeit mit diesen Leitfaden zu wahren:
- sudo nano /etc/nginx/sites-available/myproject
Öffnen Sie einen Serverblock und weisen Sie Nginx an, den Standardport 80
abzuhören. Wir wollen ihm außerdem mitteilen, diesen Block für Anfragen für den Domänennamen unseres Servers zu verwenden:
server {
listen 80;
server_name your_domain www.your_domain;
}
Als Nächstes fügen wir eineSpeicherort hinzu, der mit jeder Anfrage übereinstimmt. Innerhalb dieses Blocks schließen wir die Datei proxy_params
ein, die einige allgemeine Proxying-Parameter angibt, die eingestellt werden müssen. Wir übergeben dann die Anfragen an das Socket, das wir mit der Anweisung proxy_pass
definiert haben.
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 abschließend die Datei.
Um die Nginx-Serverblockkonfiguration zu aktivieren, die Sie gerade erstellt haben, verknüpfen Sie die Datei mit dem Verzeichnis sites-enabled
:
- sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
Mit der Datei in diesem Verzeichnis können Sie auf Syntaxfehler testen:
- sudo nginx -t
Wenn eine Rückmeldung ohne Fehleranzeige erfolgt, starten Sie den Nginx-Prozess neu, um die neue Konfiguration auszulesen:
- sudo systemctl restart nginx
Abschließend wollen wir noch einmal die Firewall anpassen. Wir brauchen keinen Zugriff über Port 5000
, sodass wir diese Regel entfernen können. Wir können dann vollen Zugriff auf den Nginx-Server zulassen:
- sudo ufw delete allow 5000
- sudo ufw allow 'Nginx Full'
Sie sollten nun in Ihrem Webbrowser zu dem Domänennamen Ihres Servers navigieren können:
http://your_domain
Sie sollten die Ausgabe Ihrer Anwendung sehen:
Wenn Sie Fehler feststellen, versuchen Sie, Folgendes zu überprüfen:
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.Um sicherzustellen, dass der Datenverkehr zu Ihrem Server sicher bleibt, benötigen wir ein SSL-Zertifikat für Ihre Domäne. Um ein Zertifikat zu erhalten, gibt es mehrere Möglichkeiten. U. a. können Sie ein kostenloses Zertifikat von Let’s Encrypt anfordern, ein selbst signiertes Zertifikat generieren oder ein Zertifikat von einem anderen Anbieter erwerben. Konfigurieren Sie Nginx entsprechend, um das Zertifikat zu nutzen, indem Sie den Schritten 2 bis 6 von Erstellen eines selbst signierten SSL-Zertifikats für Nginx in Ubuntu 20.04 folgen. Wir nutzen aus praktischen Gründen die erste Option.
Installieren Sie das Nginx-Paket von Certbot mit apt
:
- sudo apt install python3-certbot-nginx
Certbot bietet eine Vielzahl von Möglichkeiten, um SSL-Zertifikate über Plugins zu erhalten. Das Nginx-Plugin übernimmt die Neukonfiguration von Nginx und das Neuladen der Konfiguration, wenn nötig. Geben Sie Folgendes ein, um dieses Plugin zu verwenden:
- sudo certbot --nginx -d your_domain -d www.your_domain
Damit wird certbot
mit dem --nginx
Plugin ausgeführt, wobei über -d
die Namen angegeben werden, für die das Zertifikat gültig sein soll.
Wenn Sie Certbot
zum ersten Mal ausführen, werden Sie aufgefordert, eine E-Mail-Adresse einzugeben und die Bedingungen des Dienstes zu akzeptieren. Danach kommuniziert Certbot
mit dem Let’s Encrypt-Server und stellt dann anhand einer Prüfung sicher, dass Sie die Domäne, für die Sie das Zertifikat anfordern, auch kontrollieren.
Nach erfolgreicher Überprüfung fragt certbot
, 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):
Treffen Sie Ihre Wahl und drücken Sie dann ENTER
. Die Konfiguration wird aktualisiert und Nginx zum Abholen der neuen Einstellungen neu geladen. Certbot
schließt mit einer Mitteilung, 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 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
Wenn Sie die Nginx-Installationsanweisungen in den Voraussetzungen befolgt haben, benötigen Sie die redundante HTTP-Profil-Zulassung nicht mehr:
- sudo ufw delete allow 'Nginx HTTP'
Um die Konfiguration zu überprüfen, navigieren Sie mit https://
: erneut in Ihre Domäne:
https://your_domain
Sie sollten wieder die Ausgabe Ihrer Anwendung sowie den Sicherheitsindikator Ihres Browsers sehen, der jetzt darauf hinweist, dass die Site sicher ist.
In diesem Leitfaden haben Sie eine einfache Flask-Anwendung in einer virtuellen Python-Umgebung erstellt und gesichert. Sie haben einen WSGI Einstiegspunkt erstellt, sodass jeder beliebige WSGI-fähige Anwendungsserver sich damit verbinden kann, und dann den Gunicorn App-Server so konfiguriert, dass er die Funktion bereitstellt. Danach haben Sie eine systemd-Dienstdatei erstellt, um den Anwendungsserver automatisch beim Boot zu starten. Außerdem haben Sie einen Nginx-Serverblock erstellt, der den Web-Client-Verkehr an den Anwendungsserver übergibt und externe Anfragen und den gesicherten Datenverkehr mit Let’s Encrypt an Ihren Server weiterleitet.
Flask ist ein sehr einfaches, aber extrem flexibles Framework, das Ihren Anwendungen Funktionalitäten bereitstellt, ohne hinsichtlich Struktur und Gestaltung zu restriktiv zu sein. Sie können den in diesem Leitfaden beschriebenen allgemeinen Stack verwenden, um die von Ihnen gestalteten Flask-Anwendungen zu bedienen.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!