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 Sie Ihre Anwendung in einem Container ausführen möchten, finden Sie in unserem Artikel zu Podman die wichtigsten Informationen.

Container ermöglichen Ihnen, Ihre 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 Ihnen, Ihre Anwendung zu skalieren, indem sie sie von anderen Prozessen im System isolieren.

Anforderungen

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

1. Python installieren

Auf Ihrem 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.*

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

Abhängigkeiten

Zum Betrieb von Python-Applikation per uWSGI ist es erforderlich, dass Nine einige Python-Abhängigkeiten installiert. Falls dies Ihre erste pyenv-Installation auf diesem Managed Server sein sollte, wenden Sie sich bitte per E-Mail unter an uns. Gerne installieren wir die erforderlichen Abhängigkeiten.

  1. Führen Sie das Installationsskript mit folgendem Befehl aus:

    curl https://pyenv.run | bash
  2. Führen Sie den folgenden Befehl aus, um Ihre ~/.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 Ihrer .bashrc hinzugefügt. Um pyenv über das CLI zu verwenden, muss die .bashrc erneut eingelesen werden.:

    source .bashrc
  4. Installieren Sie 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, Ihre Python-Anwendungen voneinander zu trennen, indem Sie virtuelle Umgebungen, oder kurz venv, verwenden.

  1. Erstellen und aktivieren Sie eine neue Umgebung:

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

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

3. Deployment der Applikation

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

  1. Installieren Sie die Django-CLI:

    (.venv) pip install Django
  2. Kopieren Sie die Anwendungsdateien auf Ihren Server:

    rsync -Hav --delete --exclude='node_modules/*' --exclude='logs/*' --exclude='.git/*' --exclude='.venv/*' ./local_project www-data@server.nine.ch:app/
  3. Installieren Sie 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 Ihrer Anwendung ab. Das folgende Beispiel geht davon aus, dass eine Django-App eingesetzt wird.

  1. Erstellen Sie 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 \
    --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. Starten Sie den Dienst:

    touch ~/app/env # Stellen Sie 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. Stellen Sie sicher, dass die .bashrc korrekt geladen wird
  2. Überprüfen Sie, ob der Dienst korrekt gestartet wurde: systemctl --user status app.service
  3. Überprüfen Sie die Log-Ausgabe: journalctl --user -f

Weitere Informationen zur Verwendung von Systemd finden Sie im folgendem Support-Artikel.

5. Webserver konfigurieren

https

Dadurch sollte Ihre Anwendung über http zugänglich sein. Um https-Unterstützung hinzuzufügen, verwenden Sie 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 Ihrem Managed Server sind bereits zwei nine-manage-vhost Vorlagen für diesen Anwendungsfall vorinstalliert: proxy und proxy_letsencrypt.

Erstellen Sie 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 Ihre Applikation angesprochen.