Skip to content

Instantly share code, notes, and snippets.

  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save tocsinde/98c423da2724d23c02ff to your computer and use it in GitHub Desktop.
Anleitung für Flask auf Uberspace.

Was ist das hier?

Gestartet ist dieser Gist als lesbare (Markdown-) Version des leider schwer lesbaren Gists von dAnjou vom Januar 2015, der aus dem Uberspace-Wiki verlinkt ist. Jetzt allerdings, im Januar 2016, stellt sich heraus, dass diese Anleitung aus mehreren Gründen nicht mehr ohne weiteres funktioniert. Deswegen habe ich sie dem Stand der Erkenntnisse angepasst und überarbeitet. Dennoch meinen herzlichen Dank an dAnjou für den Kickstart, ohne den alles viel kniffliger gewesen wäre :3

Mit dem Flask-Framework entwickeln

Flask ist ein Micro-Framework für Webapplikationen auf Python-Basis. Und da Du in Deinem Uberspace selbst Python-Module installieren kannst, solltest Du auch Flask-Anwendungen im Uberspace laufen lassen können.

Trotz acht Jahren Python 3 und der unerquicklichen Unicode-Behandlung von python 2 bin ich weiterhin an Python 2 gebunden, weil nicht alle Umgebugen in denen ich arbeite "schon" Python 3 unterstützen. Daher setze ich auch hier auf Python 2, wegen des deutlich erweiterten unittest-Moduls allerdings auf Python 2.7, das im Uberspace mit python2.7 aufgerufen wird.

Mein Ziel ist es also jetzt, mit Dir eine Flask 0.10.1-Anwendung auf Python 2.7 im Uberspace zu deployen.

Flask installieren

[mclane@orion ~]$ easy_install-2.7 --user Flask

Erklärung:

  • easy_install: Moderner wäre pip2.7 gewesen. Mir gefällt allerdings inzwischen die Speicherung in .egg-Dateien sehr gut, die man einfach löschen kann. Und da ich damit losgelegt habe, hat es einigen Charme, es auch weiter zu verwenden, damit alle installierten Packages im selben Verzeichnis abgelegt werden. Da die ==-Syntax zur Versionangabe (siehe unten) auch von pip unterstützt wird, kannst Du die Art der Installation wählen, die Du auch sonst verwendest.
  • easy_install-2.7: Die python-Version sollte man auf jeden Fall angeben, weil nicht immer ganz klar ist, zu welcher pathon-Version das versionslose easy_install (oder pip) gehört. Bei mir wäre es python2.6 gewesen, wie /usr/bin/env easy_install und die erste Zeile von /usr/bin/easy_install zeigen.
  • --user: Natürlich kannst Du Module nicht global installieren, sondern nur für Deinen User. Im Falle von easy_install-2.7 werden diese dann in ~/.local/lib/python2.7/site-packages installiert, wenn Du nichts anders bestimmst. Die benötigten Verzeichnisse werden automatisch angelegt.

Jetzt könnten wir schon Anwendungen bauen und sie im eingebauten Entwicklungsserver ausführen.

Hallo, Welt.

[...]

flup installieren

Zum produktiven Einsatz im Internet eignet sich der Entwicklungsserver allerdings nicht. Stattdessen sollte die Anwendung über den Apache-Webserver bereitgestellt werden. Der Uberspace erledigt das mit FastCGI. Man kann das auf den meisten Servern eingesetzte Modul mod_fcgid mögen oder nicht – so ist es nun mal. Um die Flask-Anwendung an dieses Modul anzubinden, benötigen wir entsprechend der Deployment-Anleitung von Flask noch flup:

[mclane@orion ~]$ easy_install-2.7 --user flup==1.0.3.dev-20110405

Erklärung:

  • ==1.0.3.dev-20110405: mit flup ohne Versionaangabe würdest Du die aktuelle Version vom Dezember 2015 installieren. Dort hat allerdings jemand – vermutlich versehentlich – die Python 2-Unterstützung kaputtrepariert.
  • -20110405: Ja, leider war nichts besseres zu finden, als die 5 Jahre alte Version eines offensichtlich kaum noch gepflegten und weitgehend undokumentierten Packages, um unsere python2.7-Anwendung ans mod_fcgid im Apache-Server anzuschließen. Dennoch sollten wir dankbar sein, überhaupt einen solchen Adapter für lau ins Netz zu finden...

Wie dem auch sei: Jetzt kannst Du Dein erstes Flask-Projekt ins Netz stellen.


Flask-Projekt anlegen und konfigurieren

TODO

  • Hello-world-Programm from scratch statt Installation einer weiteren unbekannten Komponente. Dann entfällt auch das Gefummel mit der Datenbank.

Beispielhaft verwenden wir hier eine Beispielanwendung von Flask. Diese nennt sich Flaskr und stellt eine sehr minimale Blog-Software dar. Wir nennen das Projekt hier also der Einfachheit halber flaskr und möchten es in unserem Home-Verzeichnis anlegen. Wir holen uns also erstmal die Quellen für Flask, in denen die Beispielanwendung zu finden ist und kopieren uns diese heraus. Danach können die Flask-Quellen wieder gelöscht werden.

[danjou@orion ~]$ git clone https://github.com/mitsuhiko/flask.git
[danjou@orion ~]$ cp -r flask/examples/flaskr ./
[danjou@orion ~]$ rm -r flask

Jetzt sollte im Home-Verzeichnis ein Ordner flaskr liegen. In diesem befindet sich die Beispielanwendung. Sie ist schon für den Einsatz bereit. Allerdings sollte man noch den Pfad zur SQLite-Datenbank ändern, da diese, so wie es jetzt ist, in /tmp liegen wird, wo sie natürlich nicht hingehört. Aber: in der Kürze liegt die Würze, und deshalb geht es gleich weiter mit wichtigeren Sachen.

Datenbank initialisieren

Die README von Flaskr beschreibt wie man die Datenbank initialisiert. Man wechselt in der Verzeichnis der Anwendung, öffnet die interaktive Python-Shell und führt eine kleine Anweisung aus:

[danjou@orion ~]$ cd flaskr/
[danjou@orion flaskr]$ python2.7 
Python 2.7.1 (r271:86832, Jun 10 2011, 16:05:03) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-50)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from flaskr import init_db; init_db()

Mit Strg+D verlässt man die Python-Shell wieder. Das war's für diesen Schritt.

Deployment mit FastCGI

TODO

  • Funktionieren tut das folgende zur Zeit (1.16) leider nicht. Da das seit 2011 ungepflegte und im Dezember 2015 kaputtreparierte Paket flup zur Einbindung in FCGI verwendet wird, muss man entweder die veraltete flup-Version von 2011 verwenden oder beim Start via FCGI kommt ein Fehler File ".../fcgi_base.py", line 45, in <module> ImportError: No module named _dummy_thread.
  • Ticket bei Uberspace läuft.
  • Sofern es weiterhin FastCGI sein muss, könnte man flipflop versuchen, was zumindestens nicht kaputtrepariert worden ist.

Es gibt nun verschiedene Varianten, Flask ins Web zu bringen: Mit dem eingebauten Development-Webserver, mit mod_wsgi, mit CGI, oder eben auch mit FastCGI. Uberspace setzt für Python-Anwendungen auf FastCGI.

Lege dir einfach innerhalb deines fcgi-bin-Verzeichnisses einen Wrapper an, der deine Flask-Installation startet. Diese sieht etwas anders aus als in der Flask-Dokumentation, da Uberspace ein etwas anderes Setup hat:

[mclane@orion ~]$ cat <<__EOF__ > ~/fcgi-bin/flaskr.fcgi
#!/usr/bin/env python2.7
import sys
sys.path.insert(0, "/home/mclane/flaskr")
from flup.server.fcgi import WSGIServer
from flaskr import app
if __name__ == '__main__':
    WSGIServer(app).run()
__EOF__

Das sys.path.insert dient dazu, dass Python weiß, in welchem Verzeichnis das Modul flaskr zu finden ist, von dem es ein paar Zeilen später die Anwendung importiert; wenn dein Flask-Projekt in einem anderen Pfad angelegt hast, musst du entsprechend jene Angabe hier anpassen - sie muss auf dem Verzeichnis stehen, in dem dein Projekt liegt. Zum guten Schluss muss die Datei noch ausführbar gemacht werden:

[mclane@orion ~]$ chmod 755 ~/fcgi-bin/flaskr.fcgi

Das war's!

TODO

  • "Test" der Anwendung im Browser und auf der Konsole. Hier würde nämlich jetzt die URL hingehören.

Neustarten der Anwendung

Wird Anwendungscoding geändert oder werden neue Softwareversionen installiert, kann es nötig sein, die Flask-Anwendung neu zu starten. Das kann man ganz einfach erreichen, indem man den laufenden Prozess beendet:

[mclane@orion ~]$ pkill -f "python2.7 frog.fcgi"

Dabei muss frog.fcgi natürlich durch das jeweils gestartete fcgi-Programm ersetzt werden. Einfach pkill python2.7 oder killall python2.7 ist weniger empfehlenswert, weil auch andere laufende python2.7-Skripte dann gekillt würden.

Mit dem nächsten Aufruf der URL startet das FastCGI-Modul im Apache Webserver (also mod_fastcgi bzw. mod_fcgid) die Applikation automatisch wieder.

Ausprobieren

Ruf den FastCGI-Wrapper einfach im Browser auf - im konkreten Fall wäre das https://mclane.orion.uberspace.de/fcgi-bin/flaskr.fcgi/. Tada! Du solltest nun die Anwendung benutzen können. Die Zugangsdaten für den Login findest du in der Datei flaskr.py im Projektverzeichnis.

URL aufhübschen

Natürlich ist .../fcgi-bin/flaskr.fcgi/... keine übermäßig hübsche URL. Das lässt sich mit einer .htaccess-Datei aber flugs regeln, die hier beispielsweise alle Requests auf die URL flask/... auf den FastCGI-Pfad umschreibt:

[danjou@orion ~]$ cat <<__EOF__ >> ~/html/.htaccess
RewriteEngine on
RewriteRule ^flaskr/(.*)$ /fcgi-bin/flaskr.fcgi/$1 [QSA,L]
__EOF__

Probier's aus - nun solltest du die Anwendung über https://danjou.orion.uberspace.de/flaskr/ erreichen können.

Richtig deployen

[... git ...]

Wie geht es weiter?

Unser Part bei der Sache ist, wie du Flask bei Uberspace zum Laufen bekommst, also sozusagen der administrative Teil. Dein eigener Job ist es nun, Flask-Anwendungen zu entwickeln - da legen wir dir dir das offizielle Flask Tutorial oder das Flask Mega Tutorial von Miguel Greenberg ans Herz.

Viel Erfolg!

@Brice187
Copy link

Brice187 commented May 20, 2017

Für Python 3.6 auf Uberspace sieht mein fcgi Skript folgendermaßen aus:

 #!/usr/bin/env python3.6

# This is the path relative to /
# If your application is available at www.domain.com/subdir/subdir2/myapplication this should be /subdir/subdir2/myapplication
RELATIVE_WEB_URL_PATH = '/'

import os
# This points to the application on the local filesystem.
LOCAL_APPLICATION_PATH = os.path.expanduser('~') + '/html/ccss'

import sys
sys.path.insert(0, LOCAL_APPLICATION_PATH)

from flipflop import WSGIServer
from ccss import app

class ScriptNamePatch(object):
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        environ['SCRIPT_NAME'] = ''
        return self.app(environ, start_response)

app = ScriptNamePatch(app)

if __name__ == '__main__':
    WSGIServer(app).run()

wobei ccss meine Flask-App ist. Man muss noch 'pip3 install flipflop --user' machen

@tocsinde
Copy link
Author

Vielen Dank dafür :)

@dolonnen
Copy link

dolonnen commented Jul 7, 2017

@Brice187:

Was für was hast du die Klasse ScriptNamePath?

@dolonnen
Copy link

dolonnen commented Jul 7, 2017

Mein (einfaches) fcgi-Script für python 3.6:

#!/usr/bin/env python3.6

import sys
sys.path.insert(0, "/home/bgraph/bin")

from getStreamCreds import app
from flipflop import WSGIServer

WSGIServer(app).run()

@tocsinde
Copy link
Author

tocsinde commented Aug 3, 2017

Was für was hast du die Klasse ScriptNamePath?

Die dient für den Subfolder-Support, falls man das Script nicht direkt im Root der (Sub-)Domain laufen lassen mag.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment