Webanwendung Server Setup für kollaborative Entwicklung


Workflows

TL;dr: Or, you could just use Gitlab or Github..

Für die Entwicklung einer Webanwendung mit Flask kann es nützlich sein, dass Änderungen am Code schnell auf einen Server übertragen und dort direkt ausgespielt werden können. Zwei Fälle sind für mich hier relevant: Die Zusammenarbeit am Code mit Leuten, die selber keine Flask-Entwicklungsumgebung einrichten, aber Änderungen beisteuern und ausprobieren wollen, und das Reflektieren von einfachen Änderungen bei der iterativen Entwicklung im Kontakt mit Nutzer*innen.

Flask bietet einen integrierten Entwicklungsserver, mit dem eine Anwendung lokal gestartet werden kann. Wird der Server im Debug-Modus gestartet werden Änderungen direkt in den ausgespielten Seiten angezeigt. Das heißt der Entwicklungsserver erkennt, dass eine Änderung gemacht wurde, und führt die notwendigen Reloads durch. Der Server im wird im Debug-Modus gestartet mit flask --app my_app --debug run (ab Flask-Version 2.2.x). Jetzt können alle Änderungen am Code, die Änderungen in der Ausgabe hervorbringen, direkt im Browser beobachtet und geprüft werden. Ich verwende das zum Beispiel für die Anpassung von Templates für ausgegebene Seiten.

Dieser Entwicklungs-Workflow funktioniert wenn alleine entwickelt wird. Was machen wir wenn wir kollaborativ entwickeln? Mit der Versionierungslösung Git können Änderungen vom lokalen Rechner in ein Git-Repository und vom Repository wieder auf lokale Rechner übertragen werden. Wenn also zwei Leute an einer Anwendung arbeiten, spielen beide ihre Änderungen ins Repository und holen sich die Änderungen der jeweils anderen Person auch aus diesem Repository. Beide entwickeln also lokal mit einem eigenen lokalen Entwicklungsserver, der Code wird über das Repository geteilt.

Aber was tun wenn Leute an der Anwendungsentwicklung beteiligt sind, die die Anwendung nicht lokal laufen lassen wollen oder können, weil sie vielleicht CSS beitragen, aber normalerweise nicht mit Python arbeiten? Dann fehlt der lokale Entwicklungsserver und wir brauchen einen entfernten Entwicklungsserver, auf dem die Anwendung installiert ist, läuft, und von außen erreichbar ist. Änderungen am Code müssen so übertragen werden können, dass sie nachvollziehbar sind, also rückgängig gemacht werden können, und direkt vom Server reflektiert werden. Wir arbeiten in diesem Szenario schon mit Git. Der Code für die Anwendung liegt in einem Git-Repository auf dem Server, das für alle Beiträger*innen erreichbar ist. Um Änderungen auf den Server zu übertragen reicht es also, sie wie bei der normalen Arbeit mit Git mit dem Befehl git push zu übertragen. Die Beiträger*innen werden dadurch entlastet: Es reicht, wenn Änderungen ins zentrale Repository übertragen werden. Von dort werden sie automatisiert auf den Server gespiegelt und direkt in der laufenden Anwendung reflektiert.

Server einrichten

Der Server wird so eingerichtet, dass

  1. Änderungen via git direkt auf den Server übertragen werden können
  2. der Server für die Webanwendung im Reload-Modus läuft, also Änderungen an der Anwendung direkt reflektiert werden

Für Punkt a) wird ein Git-Repository benötigt, das für alle Beteiligten zugänglich ist. Auf dem Server wird dann ein Skript eingerichtet, das regelmäßig die Änderungen aus dem Repository auf den Server holt. Das Repo kann auf dem Server liegen oder anderswo. Es muss lediglich sichergestellt werden dass die Änderungen automatisiert übertragen werden kann. Mein Setup:

  • Ein leeres Git-Repo auf dem Server einrichten, auf dem auch die Anwendung läuft. Ordner anlegen, dann im Ordner das Repo einrichten mit git init --bare.
  • Dieses Repo auf meinem lokalen git repo als remote repository setzen mit git remote add origin ssh://[username]@example.org:[path_to_git]
  • Inhalte übertragen mit git push origin main
  • Auf dem Server das Repo in einem eigenen Anwendungsverzeichnis klonen mit git clone [path_to_git]. Das ist notwendig, weil das neu angelegte git-repo aus dem ersten Schritt kein Arbeitsverzeichnis ist, sondern eine etwas andere Struktur hat. Dort liegen keine Ordner und Dateien, die bearbeitet werden können.
  • Das regelmäßige Update des geklonten Repos automatisieren.

Für Punkt b) nutze ich den Anwendungsserver Gunicorn. Gunicorn bietet eine Reloadfunktion, die einfach mit der Option --reload aktiviert wird. Die Flask-Anwendung wird mit Gunicorn ausgeführt und ist dann über die angezeigte Adresse erreichbar. Der Gunicorn-Befehl muss so ausgeführt werden, dass er unabhängig von der aktiven SSH-Session läuft, zum Beispiel mit einem Terminal-Multiplexer wie screen oder tmux.

Im Ergebnis können alle Beteiligten ihre Änderungen am Code auf dem Server testen. Zu beachten ist, dass die Bereitstellung der Anwendung im Netz ein Sicherheitsrisiko darstellt, das durch entsprechende Zugangsbeschränkungen möglichst gering gehalten werden sollte.