Python: Erweiterte Anwendungen

Weiterführende Schritte mit Ihren Python-Bereitstellungen

👋 Willkommen bei der Stackhero-Dokumentation!

Stackhero bietet eine einsatzbereite Python-Cloud-Lösung, die zahlreiche Vorteile bietet, darunter:

  • Deployen Sie Ihre Anwendung in Sekundenschnelle mit einem einfachen git push.
  • Verwenden Sie Ihren eigenen Domainnamen und profitieren Sie von der automatischen Konfiguration von HTTPS-Zertifikaten für erhöhte Sicherheit.
  • Genießen Sie beruhigende automatische Backups, Ein-Klick-Updates und eine einfache, transparente und vorhersehbare Preisgestaltung.
  • Erhalten Sie optimale Leistung und robuste Sicherheit dank einer privaten und dedizierten VM.

Sparen Sie Zeit und vereinfachen Sie Ihr Leben: Es dauert nur 5 Minuten, um die Python-Cloud-Hosting-Lösung von Stackhero auszuprobieren!

Bisher haben wir den Befehl git push stackhero main verwendet, um den main Branch in die Produktion zu bringen.

Wenn Sie einen anderen Branch bereitstellen müssen, können Sie diesen Befehl verwenden, wobei <BRANCH> der Name des Branches ist, den Sie bereitstellen möchten:

git push stackhero <BRANCH>:main

Zum Beispiel, wenn Sie den production Branch bereitstellen möchten, führen Sie einfach aus:

git push stackhero production:main

Sie können wählen, einen Tag anstelle eines Branches bereitzustellen. Um einen bestimmten Tag bereitzustellen, ersetzen Sie <TAG> durch den gewünschten Tag im folgenden Befehl:

git push stackhero '<TAG>^{}:main'

Zum Beispiel, um den Tag v1.0.0 bereitzustellen, würden Sie ausführen:

git push stackhero 'v1.0.0^{}:main'

Die ^{} Syntax stellt sicher, dass Sie den getaggten Commit und nicht die Tag-Referenz selbst pushen.

Zusätzlich zur Bereitstellung von Branches oder Tags können Sie auch einen spezifischen Commit mithilfe seines Hashes bereitstellen. Ersetzen Sie <COMMIT_HASH> durch den Hash des Commits, den Sie bereitstellen möchten:

git push -f stackhero <COMMIT_HASH>:main

Zum Beispiel, um den Commit mit dem Hash abcde bereitzustellen, führen Sie aus:

git push -f stackhero abcde:main

Wenn ein kürzlicher Einsatz Probleme verursacht hat, können Sie zu einem früheren Commit zurückkehren, indem Sie diesen Commit bereitstellen. Identifizieren Sie zuerst den Commit-Hash, indem Sie ausführen:

git log

Dieser Befehl zeigt das Datum, den Hash und die Beschreibung jedes Commits an.

Zum Beispiel könnte die Ausgabe so aussehen:

git log

commit cccc8b3ebdccb9abc1926ef49ee589dae5c5fe06 (HEAD -> main, stackhero/main)
Author: Developer
Date:   Fri Apr 28 09:36:18 +0000

    Break the code

commit bbbb622301772072c3d82f3cc0d91e29e6e84901
Author: Developer
Date:   Wed Apr 26 12:49:28 +0000

    Update the code

commit aaaa1d8b06535b413e0df8298ccf52339dfef3ff
Author: Developer
Date:   Wed Apr 26 12:44:50 +0000

    Improve the code

Wenn der aktuelle Produktionseinsatz der Commit "Break the code" (Hash beginnend mit cccc) ist und Sie zum vorherigen Commit "Update the code" (Hash beginnend mit bbbb) zurückkehren möchten, führen Sie aus:

git push -f stackhero bbbb622301772072c3d82f3cc0d91e29e6e84901:main

Um zu verhindern, dass fehlerhafter Code bereitgestellt wird und die Stabilität Ihrer Produktion zu erhöhen, wird dringend empfohlen, eine "Staging"-Umgebung zu haben.

Zwischen Entwicklung und Produktion gelegen, bietet die Staging-Umgebung eine nahezu identische Replik der Produktionsumgebung. Sie hilft Ihnen, Ihren Code gründlich zu testen, bevor er live geht.

Die Nutzung von Staging erhöht Ihr Vertrauen in die Funktionalität und Leistung Ihres Codes, was zu einem robusteren Produktionseinsatz führt.

Dieser Umwelttyp wird später in der Dokumentation behandelt.

Eine Staging-Umgebung ist eine bewährte Methode, wenn sie zusammen mit Entwicklungs- und Produktionsumgebungen verwendet wird. Sie repliziert die Produktionsumgebung, sodass Sie Updates und Änderungen testen können, bevor sie live gehen, und so das Risiko von Problemen in der Produktion verringern.

Eine Staging-Umgebung muss die Produktionsumgebung genau widerspiegeln.

Sie sollte jedoch eine geklonte Version Ihrer Produktionsdatenbank oder verbundenen Dienste verwenden, anstatt der Live-Produktionsdatenbank.

Wenn Ihr Python-Dienst von Datenbanken oder anderen Diensten abhängt, erstellen Sie sie in einem neuen <Project> - Staging Stack neu.

Folgen Sie diesen Schritten, um eine Staging-Umgebung mit Stackhero einzurichten:

  1. Benennen Sie auf dem Stackhero-Dashboard Ihren bestehenden Stack von <Project> in <Project> - Production um. Zum Beispiel, wenn Ihr Projekt Chat Bot heißt, wird der Stack zu Chat Bot - Production.
  2. Erstellen Sie einen neuen Stack namens <Project> - Staging. Für das Projekt Chat Bot wird der Stack zu Chat Bot - Staging.
  3. Starten Sie einen Python-Dienst innerhalb des Staging-Stacks.
  4. Rufen Sie den git remote Befehl ab und folgen Sie den Anweisungen in der Bereitstellung in der Staging-Umgebung Dokumentation.

Diese Konfiguration stellt sicher, dass Sie eine voll funktionsfähige Staging-Umgebung haben, um Updates vor der Produktionsbereitstellung zu testen.

Es wird dringend empfohlen, separate Staging- und Produktionsumgebungen zu pflegen. Um mehrere Umgebungen zu verwalten, beginnen Sie damit, das aktuelle Remote-Repository umzubenennen. Zum Beispiel, benennen Sie das Remote stackhero in stackhero-production um mit:

git remote rename stackhero stackhero-production

Erstellen Sie als Nächstes einen neuen Python-Dienst für Ihre Staging-Umgebung. Rufen Sie den git remote add Befehl ab und ändern Sie ihn, indem Sie <XXXXXX> durch die Domain Ihres Dienstes ersetzen:

  • Originalbefehl:

    git remote add stackhero ssh://stackhero@<XXXXXX>.stackhero-network.com:222/project.git
    
  • Geänderter Befehl:

    git remote add stackhero-staging ssh://stackhero@<XXXXXX>.stackhero-network.com:222/project.git
    

Sie können dann in beide Umgebungen mit den folgenden Befehlen bereitstellen:

  • Bereitstellung in Staging:

    git push stackhero-staging main
    
  • Bereitstellung in Produktion:

    git push stackhero-production main
    

Um den Bereitstellungsprozess zu verbessern, empfehlen wir die Verwendung der verbesserten Makefile-Version.

Mit diesem verbesserten Makefile wird die Bereitstellung in Produktion oder Staging so einfach wie das Ausführen von make deploy-production oder make deploy-staging.

Unten ist ein verbessertes Makefile, das mehrere Regeln unterstützt:

  • make dev (oder einfach make): Startet die Anwendung im Entwicklungsmodus.
  • make deploy: Stellt die Anwendung auf dem Remote namens stackhero bereit. Dies funktioniert gut, wenn Sie nur eine Stackhero-Instanz haben.
  • make deploy-production: Stellt die Anwendung auf dem Remote namens stackhero-production bereit.
  • make deploy-staging: Stellt die Anwendung auf dem Remote namens stackhero-staging bereit.

Dieses Makefile ist so konzipiert, dass es Situationen handhabt, in denen sich der Code nicht geändert hat, indem es den "Everything up-to-date" Fehler vermeidet.

Kopieren Sie den folgenden Inhalt und fügen Sie ihn als Ihr neues Makefile ein:

# Standardregel, die ausgeführt wird, wenn "make" ohne Argument aufgerufen wird
.DEFAULT_GOAL := dev


# Stackhero für Python wird die "run" Regel auf Ihrer Instanz ausführen.
# Dies ist der Befehl, der sowohl in Ihren Produktions- als auch in Ihren Staging-Umgebungen ausgeführt wird.
run:
  ENV=production gunicorn app:app \
    --error-logfile - \
    -b 0.0.0.0:8080


# Der Befehl, der in der Entwicklungsumgebung verwendet wird
dev:
  python app.py


# Regel "deploy" zur Bereitstellung auf der Instanz "stackhero".
# Geeignet, wenn Sie nur eine Instanz haben.
deploy:
  @$(MAKE) -s deploy-script DEPLOY_REMOTE=stackhero DEPLOY_BRANCH=main


# Die "deploy-*" Regeln stellen auf einer Instanz bereit, die "stackhero-*" heißt.
# Zum Beispiel, das Ausführen von "make deploy-production" stellt auf "stackhero-production" bereit,
# oder "make deploy-staging" stellt auf "stackhero-staging" bereit.
deploy-%:
  @$(MAKE) -s deploy-script DEPLOY_REMOTE=stackhero-$* DEPLOY_BRANCH=main


# Interne Bereitstellungsregel. Nicht ändern.
deploy-script:
  @echo "Bereitstellung des Branches \"${DEPLOY_BRANCH}\" auf \"${DEPLOY_REMOTE}\"..."
  @echo

  @if [ -n "$$(git status --porcelain)" ]; then \
    echo "Kann nicht bereitstellen, da es nicht festgeschriebene Änderungen gibt:"; \
    echo "\e[0m"; \
    git status -s; \
    echo ""; \
    echo "\e[0;31m"; \
    echo "Sie können diesen Befehl verwenden, um die Änderungen festzuschreiben:"; \
    echo "git add -A . && git commit -m \"Ihre Nachricht\""; \
    echo "\e[0m"; \
    exit 1; \
  fi

  @git push --dry-run ${DEPLOY_REMOTE} ${DEPLOY_BRANCH} 2>&1 | grep -q -F "Everything up-to-date"; \
  EXIT_CODE=$$?; \
  if [ $$EXIT_CODE -eq 0 ]; then \
    echo -n "Nichts Neues zu bereitstellen... Bereitstellung erzwingen (dies wird einen neuen Commit erstellen)? (y/N) "; \
    read answer && \
    case $$answer in \
      y|Y|yes|YES) \
      git commit --allow-empty -m "Force update for deploy purpose to \"${DEPLOY_REMOTE}\"" ; \
      ;; \
    *) \
      echo "Nichts zu bereitstellen!"; \
      exit 1; \
      ;; \
    esac \
  fi

  git push ${DEPLOY_REMOTE} ${DEPLOY_BRANCH}

Irgendwann müssen Sie Geheimnisse wie Tokens und Passwörter für Datenbanken oder Drittanbieterdienste speichern. Es ist wichtig, diese sicher zu speichern. Vermeiden Sie es, sie direkt in Ihrem Repository oder Code einzubetten, da dies ein erhebliches Sicherheitsrisiko darstellt.

Die Verwendung von Umgebungsvariablen bietet zwei wesentliche Vorteile:

  1. Ihre Geheimnisse werden niemals in Ihrem Git-Repository gespeichert, was das Risiko eines unbefugten Zugriffs verringert.
  2. Sie können unterschiedliche Anmeldeinformationen für verschiedene Umgebungen verwenden, z. B. eine Produktionsdatenbank in der Produktion und eine Entwicklungsdatenbank während der Entwicklung.

In einer Entwicklungsumgebung erstellen Sie eine .env Datei im Stammverzeichnis Ihres Projekts. Diese Datei sollte von Git ausgeschlossen werden, um sicherzustellen, dass sie niemals festgeschrieben wird.

Um die .env Datei automatisch zu lesen, können Sie das python-dotenv Modul verwenden:

pip install python-dotenv
pip freeze > requirements.txt

Erstellen Sie dann eine .env Datei im Stammverzeichnis Ihres Projekts und fügen Sie Ihre Variablen hinzu:

ENV="development"
DATABASE_PASSWORD="secretPassword"
THIRD_API_PRIVATE_KEY="secretKey"
# ...

Stellen Sie schließlich sicher, dass die .env Datei von Git ausgeschlossen wird, indem Sie sie zu Ihrer .gitignore hinzufügen:

echo ".env" >> .gitignore

Die .env Datei ist nicht sicher genug für Staging- und Produktionsumgebungen. Stattdessen ermöglicht Stackhero Ihnen, Ihre Umgebungsvariablen direkt in der Konfiguration Ihres Python-Dienstes sicher zu speichern.

Sie können diese Variablen im Stackhero-Dashboard festlegen, indem Sie Ihren Python-Dienst auswählen und dann auf die Schaltfläche "Konfigurieren" klicken.

Python-Umgebungsvariablen auf StackheroPython-Umgebungsvariablen auf Stackhero

Der Zugriff auf Umgebungsvariablen in Python ist einfach. Verwenden Sie einfach os.environ.get() wie unten gezeigt:

import os

print(os.environ.get('ENV'))

Zum Beispiel kann die Verbindung zu einem Redis-Server unter Verwendung einer Umgebungsvariablen so erfolgen:

import os
import redis

r = redis.from_url(os.environ.get("REDIS_URL"))

In einer Entwicklungsumgebung setzen Sie REDIS_URL in Ihrer .env Datei wie folgt:

REDIS_URL="redis://localhost:6379"

Für Produktion und Staging definieren Sie REDIS_URL auf dem Stackhero-Dashboard unter der Python-Dienstkonfiguration:

REDIS_URL="rediss://default:<yourPassword>@<XXXXXX>.stackhero-network.com:6380"

Es ist eine bewährte Methode, Python-Pakete mit einer requirements.txt Datei zu verwalten. Diese Datei listet alle notwendigen Pakete und deren Versionen auf, um Ihren Code zuverlässig auszuführen.

Das Aktualisieren dieser Datei stellt sicher:

  1. Alle erforderlichen Pakete sind installiert.
  2. Es werden nur kompatible Paketversionen verwendet.

Beim Bereitstellen auf Ihrer Stackhero-Instanz werden die in requirements.txt angegebenen Pakete automatisch installiert.

Um requirements.txt zu generieren oder zu aktualisieren, führen Sie den folgenden Befehl aus, nachdem Sie neue Pakete installiert haben:

pip freeze > requirements.txt

Die meisten Python-Anwendungen verwenden die HTTP-Ports 80 (HTTP) und 443 (HTTPS).

Wenn Ihre Anwendung zusätzliche Ports öffnen muss oder andere Protokolle (TCP oder UDP) verwendet, können Sie die Einstellung "Ports Redirections" in Ihrem Python-Dienst auf dem Stackhero-Dashboard anpassen.

Für jeden zusätzlichen Port geben Sie den Eingangsport (öffentlich), den Zielport (von Ihrer Python-Anwendung verwendet) und das Protokoll (TCP oder UDP) an.

Portweiterleitungen im Stackhero-DashboardPortweiterleitungen im Stackhero-Dashboard

Zum Speichern von Dateien wie Benutzerfotos oder Dokumenten ist es in der Regel am besten, eine Objektspeicherlösung zu verwenden.

Objektspeicher ermöglicht es Ihnen, Dateien zwischen mehreren Diensten oder Instanzen zu teilen und trennt Ihren Speicher von Ihrem Code, was den besten Praktiken entspricht.

Wir empfehlen MinIO, eine schnelle und leistungsstarke Lösung, die mit dem Amazon S3-Protokoll kompatibel ist.

Wenn Sie lokalen Dateispeicher bevorzugen, können Sie den persistenten Speicher verwenden, der mit Ihrer Python-Instanz unter /persistent/storage/ bereitgestellt wird. Diese Vorgehensweise wird jedoch in den meisten Fällen nicht empfohlen.

WARNUNG: Speichern Sie niemals Daten außerhalb des Ordners /persistent/storage/!

Das Speichern von Daten außerhalb dieses Ordners kann zu Datenverlust führen, wenn Ihre Instanz neu gestartet, aktualisiert oder wenn neuer Code gepusht wird.

Auf macOS kann es umständlich sein, jedes Mal, wenn Sie Ihren Code pushen, das Passwort Ihres SSH-Privatschlüssels einzugeben. Während Sicherheit von größter Bedeutung ist, können Sie Ihr Passwort sicher mit Apples Schlüsselbund speichern, anstatt es aus Ihrem Schlüssel zu entfernen.

Um das Passwort für einen Schlüssel namens id_ed25519 zu speichern, führen Sie aus:

ssh-add --apple-use-keychain ~/.ssh/id_ed25519

Danach werden Sie nicht mehr nach Ihrem Schlüsselpasswort gefragt, was Zeit und Mühe spart.

Wenn Sie stattdessen einen RSA-Schlüssel verwenden, ersetzen Sie id_ed25519 durch id_rsa im Befehl:

ssh-add --apple-use-keychain ~/.ssh/id_rsa