Zum Hauptinhalt springen

Python Applikation mit uWSGI betreiben

Dieser Artikel erklärt, wie man Python-Anwendungen auf Nines Managed Servern mit uWSGI im Userspace betreibt.

Container-Deployment

Wenn du deine Anwendung in einem Container ausführen möchtest, findest du in unserem Artikel zu Podman die wichtigsten Informationen.

Container ermöglichen dir, deine Anwendung in unterschiedlichen Umgebungen betreiben zu können, ohne dabei wesentliche Anpassungen an der Applikation selbst vornehmen zu müssen. Container erleichtern zudem die Verwaltung von Abhängigkeiten und helfen dir, deine Anwendung zu skalieren, indem sie sie von anderen Prozessen im System isolieren.

Anforderungen

Für das nachfolgende Beispiel gehen wir davon aus, dass deine Anwendung wsgi unterstützt. Wenn du Django oder Flask verwendest, ist dies bereits der Fall.

1. Python installieren

Auf deinem Managed Server ist Python bereits vorinstalliert, jedoch ist die verfügbare Version basierend auf der jeweiligen Ubuntu-Version fixiert.

UbuntuPython
18.04 (Bionic)3.6.*
20.04 (Focal)3.8.*
22.04 (Jammy)3.10.*
24.04 (Noble)3.12.*

Um eine andere Python-Version unabhängig des eingesetzten Betriebssystems zu verwenden, empfehlen wir die Nutzung eines Versionsmanagers wie pyenv.

  1. Führe das Installationsskript mit folgendem Befehl aus:

    curl https://pyenv.run | bash
  2. Führe den folgenden Befehl aus, um deine ~/.bashrc zu ergänzen und die Shell neu einzulesen:

    cat << 'EOF' >> ~/.bashrc

    export PATH="$HOME/.pyenv/bin:$PATH"
    eval "$(pyenv init --path)"
    eval "$(pyenv virtualenv-init -)"
    EOF
  3. Neben der Installation von pyenv wird der Pfad der Installation sowie eine Umgebungsvariable zu deiner .bashrc hinzugefügt. Um pyenv über das CLI zu verwenden, muss die .bashrc erneut eingelesen werden.:

    source .bashrc
  4. Installiere die gewünschte Python-Version:

    pyenv install 3 # installiere neueste v3
    pyenv global 3 # als Standard setzen

2. Virtuelles Environment einrichten (venv)

Es ist eine bewährte Vorgehensweise, deine Python-Anwendungen voneinander zu trennen, indem du virtuelle Umgebungen, oder kurz venv, verwendest.

  1. Erstellen und aktiviere eine neue Umgebung:

    mkdir ~/app/ && cd ~/app/
    python -m venv .venv
  2. Installiere uWSGI in der soeben erstellten Umgebung:

    source .venv/bin/activate
    (.venv) pip install uwsgi

3. Deployment der Applikation

Die Schritte zum Deployen deiner Anwendung hängen ganz von deiner Anwendung ab. Bei Django musst du beispielsweise das Django-Paket installieren, daraufhin alle Dateien auf den Server hochladen und die Abhängigkeiten installieren:

  1. Installiere die Django-CLI:

    (.venv) pip install Django
  2. Kopiere die Anwendungsdateien auf deinen Server:

    rsync -Hav --delete --exclude='node_modules/*' --exclude='logs/*' --exclude='.git/*' --exclude='.venv/*' ./local_project www-data@server.nine.ch:app/
  3. Installiere die benötigten Abhängigkeiten:

    (.venv) pip install -r requirements.txt

4. Anwendung als Dienst ausführen

Um sicherzustellen, dass ein Dienst weiterläuft, z.B. neu gestartet wird wenn er ausfällt oder nach einem Neustart des Servers wieder startet, empfehlen wir die Verwendung eines Systemd-Benutzerdienstes.

Dieses Beispiel lädt Umgebungsvariablen von ~/app/env und führt dann uwsgi im Verzeichnis ~/app aus.

Die Konfiguration für eine solchen Systemd-Service hängt von deiner Anwendung ab. Das folgende Beispiel geht davon aus, dass eine Django-App eingesetzt wird.

  1. Erstelle die Service-Datei in ~/.config/systemd/user/app.service:

    [Unit]
    Description=app

    [Service]
    WorkingDirectory=%h/app
    Restart=always
    KillSignal=SIGQUIT
    Type=notify
    NotifyAccess=all

    Environment=PYTHON_VERSION=3.9.11
    Environment=PATH=%h/.pyenv/versions/$PYTHON_VERSION/bin:$PATH
    EnvironmentFile=%h/app/env

    ExecStart=%h/app/.venv/bin/uwsgi \
    --module=app.wsgi:application \
    --master \
    --http=127.0.0.1:3000 \
    --enable-threads \
    --threads=2 \
    --processes=4 \
    --harakiri=20 \
    --max-requests=5000 \
    --vacuum \
    --static-map /static=%h/exampleapp/static \
    --home=%h/app/.venv

    [Install]
    WantedBy=default.target

    Diese Einstellungen variieren je nach System und Anwendung. Wir empfehlen, die offizielle Dokumentation für die Konfigurationsparameter und Best Practices zu konsultieren.

  2. Starte den Dienst:

    touch ~/app/env # Stelle sicher, dass die Umgebungsdatei vorhanden ist
    systemctl --user daemon-reload
    systemctl --user enable app.service
    systemctl --user start app.service
    systemctl --user status app.service

Fehlerbehebung

  1. Stelle sicher, dass die .bashrc korrekt geladen wird
  2. Überprüfe, ob der Dienst korrekt gestartet wurde: systemctl --user status app.service
  3. Überprüfe die Log-Ausgabe: journalctl --user -f

Weitere Informationen zur Verwendung von Systemd findest du im folgendem Support-Artikel.

5. Webserver konfigurieren

https

Dadurch sollte deine Anwendung über http zugänglich sein. Um https-Unterstützung hinzuzufügen, verwende bitte proxy_letsencrypt_https, wie in nine-manage-vhosts mit Let's Encrypt dokumentiert.

Die Anwendung läuft jetzt auf einem lokalen Port. Um die Anwendung über http und https zu erreichen, muss der Webserver diese Anfragen an den lokalen Port weiterleiten.

Auf deinem Managed Server sind bereits zwei nine-manage-vhost Vorlagen für diesen Anwendungsfall vorinstalliert: proxy und proxy_letsencrypt.

Erstelle einen neuen vHost und geben den lokalen Port der Anwendung über die Variable PROXYPORT an:

$ sudo nine-manage-vhosts virtual-host create example.com --template proxy --template-variable PROXYPORT=3000 --webroot ~/exampleapp/static

Virtual Host created: example.com
example.com
===========
DOMAIN: example.com
USER: www-data
WEBROOT: /home/www-data/exampleapp/static
TEMPLATE: proxy
TEMPLATE VARIABLES: PROXYPORT
3000
ALIASES: www.example.com
example.com.server.nine.ch

Bei Aufruf der URL http://example.com.server.nine.ch wird nun deine Applikation angesprochen.