Bottle + Ubuntu + Apache2

Django, Flask, Bottle, WSGI, CGI…
dd0815
User
Beiträge: 33
Registriert: Donnerstag 25. Juli 2019, 13:57

Hallo zusammen,

ich möchte jetzt meine Bottle-Applikation auf einen Ubuntu-Server (14.04.5 LTS) laufen lassen (statt auf meinem Testrechner (Win7-64) ).

Nach erfolglosem Kampf mit Updates (python3/pip3 - aber das wäre ein Thema für ein anderes Forum) habe ich doch das vorinstallierte python 2.7.6 und bottle v0.12.0 genommen. Mit dem integrierten Testserver läuft es nun (nach Ersetzen des localhosts mit der richtigen IP), aber ich möchte nun den Apache2-Webserver (mod_wsgi) benutzen. Folgende Anleitung ist zwar ein Einstieg, aber leider nicht detailliert genug:

https://bottlepy.org/docs/dev/deploymen ... e-mod-wsgi

Ich habe wie dort beschrieben einem Verzeichnis /var/www/html/test eine Datei app.wsgi erstellt:

Code: Alles auswählen

import os
# Change working directory so relative paths (and template lookup) work again
os.chdir(os.path.dirname(__file__))

import bottle
# ... build or import your bottle application here ...
# Do NOT use bottle.run() with mod_wsgi

@route('/hello')
def hello():
    return "Hello World!"

application = bottle.default_app()
sowie eine Datei test.conf im Ordner /etc/apache2/sites-available mit dem Inhalt:

Code: Alles auswählen

<VirtualHost *>
    ServerName test.com

    WSGIDaemonProcess test user=www-data group=www-data processes=1 threads=5
    WSGIScriptAlias / /var/www/html/test/app.wsgi

    <Directory /var/www/html/test>
        WSGIProcessGroup test
        WSGIApplicationGroup %{GLOBAL}
        Require all granted
    </Directory>
</VirtualHost>
aber ich kann mir nicht vorstellen, dass Inhalt bzw. Ort stimmen... Muss das direkt in die apache2.conf? Was muss bei ServerName stehen? Was würde letztlich für eine Url rauskommen? ip/test oder ip/test/hello? (den Apache2-Server habe ich auch neu gestartet)

Vielen Dank für Eure Bemühungen & viele Grüße,
dd0815
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wieso ist die Frage bezueglich Python3/pip fuer ein anderes Forum, aber die Frage nach der APACHE-conf fuer hier? Mag ja Leute geben, die sich auskennen, aber deine Fragen sind ja hauptsaechlich Apache-bezogen. Von dem an was ich mich da erinnere: virtual hosts sind dazu gedacht, mehrere Webpraesenzen auf einer IP fahren zu koennen. Dazu wird (schon ewig) der hostname vom Client im HTTP Request mitgeschickt. Und damit kann apache dann entscheiden, fuer welchen virtuellen Server das dann ist. Da muss also hin, unter welchem FQDN du den Server erreichen willst. Und dann wird alles unter / auf die WSGI-app gemappt.

Bezueglich deiner Bemerkung der IP: das ist keine gute Idee. Nimm einfach "", das bindet auf alle lokalen Interfaces. Damit ueberlebt dein Server auch einen Wechsel der IP ohne Anpassung.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

dd0815 hat geschrieben: Dienstag 24. September 2019, 11:16 ich möchte jetzt meine Bottle-Applikation auf einen Ubuntu-Server (14.04.5 LTS) laufen lassen (statt auf meinem Testrechner (Win7-64) ).
14.04 wird seit April nicht mehr unterstützt auch nicht mit Sicherheitsupdates, es sei den du zahlst Canonical für ESM. Dementsprechend solltest du den nicht nutzen. Sollte der eine Internetverbindungen haben oder gehabt haben (selbst für ein paar Minuten), würde ich empfehlen davon auszugehen dass er kompromittiert ist.
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Und wo wir gerade bei (zu) alter Software sind: Jetzt noch Projekte mit Python 2.7 anzufangen ist auch keine gute Idee.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
noisefloor
User
Beiträge: 3855
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

auch das Setup aus Apache + mod_wsgi würde ich nicht nehmen. Ja, es funktioniert, aber die Kombi nginx als Reverse-Proxy und Gunicorn als WSGI Applikationsserver ist einfacher zu konfigurieren und einfacher zu debuggen.
Je nach dem, was du vor hast, kannst du ggf. auch nginx weg lassen und lieferst direkt über Gunicorn aus. Wobei der Aufwand, nginx als Reverse-Proxy zu konfigurieren, echt gering ist. Ist übrigens auch im Wiki von ubuntuusers.de erklärt,

Gruß, noisefloor
Benutzeravatar
noisefloor
User
Beiträge: 3855
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

Nachtrag: der Code im 1. Post entspricht _nicht_ dem aus der Bottle Doku, da ist das auch nicht so erklärt. Mit deinem Code bekommst du in der Zeile mit `@route(...)` einen Fehler, weil `route` nicht bekannt ist.

Gruß, noisefloor
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

noisefloor hat geschrieben: Dienstag 24. September 2019, 19:49 Je nach dem, was du vor hast, kannst du ggf. auch nginx weg lassen und lieferst direkt über Gunicorn aus.
Wenn der Apache schon mal da ist, kann man in dem Fall auch mod_proxy als Reverse Proxy verwenden. Das scheint nicht ganz so populär zu sein, klappt aber auch gut. Ob das leicht zu konfigurieren ist, liegt im Auge des Betrachters ;)
dd0815
User
Beiträge: 33
Registriert: Donnerstag 25. Juli 2019, 13:57

Hallo zusammen,

vielen Dank für Eure Antworten und sorry, dass ich so lange eine Reaktion darauf schuldig geblieben bin, aber andere Sachen kamen dazwischen...

Ja, ich war etwas genervt von den Update-Problemen (da fehlt mir noch ein bißchen Wissen, wie ich aktuellere Pakete auf einem Ubuntu zum Laufen bekomme) , so dass ich erstmal ein Test auf einem vorhandenen Server mit besagten Versionen machen wollte (dass Ubuntu 14.04 sowie Python 2.7. schon ziemlich alt sind, ist mir bekannt)...

Aber nun hab ich einen extra Testserver aufsetzen dürfen (HP ProLiant), auf dem jetzt Ubuntu 18.04.03 LTS, Python 3.6.8 (und 2.7.15) sowie nginx 1.14.0 laufen. Bis jetzt bin ich noch nicht bei einer Bottle-Applikation angekommen, ich hänge da jetzt auch an der Definition von Serverblöcken (sozusagen dem Pendant zu den virtuellen Hosts von Apache). Ich habe mich da an diese Anleitung gehalten:

https://www.digitalocean.com/community/ ... u-18-04-de

Das Ziel ist das Erreichen meiner Applikation unter Servername/Applikation. Der Default-Zweig funktioniert (also "Welcome to nginx" ist zu sehen), aber der Server findet meine Test-Seite nicht - Aufruf "Servername/mserp" (/var/log/nginx/access.log):

Code: Alles auswählen

172.21.6.18 - - [30/Sep/2019:12:04:16 +0000] "GET /mserp HTTP/1.1" 404 152 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:69.0) Gec
ko/20100101 Firefox/69.0"
Wie im Beispiel beschrieben habe ich unter /etc/nginx/sites-available eine Datei angelegt:

Code: Alles auswählen

server {
        listen 80;
        listen [::]:80;

        root /var/www/mserp/html;
        index index.html;

        server_name mserp www.mserp;

        location / {
                try_files $uri $uri/ =404;
        }
}
die index.html gibt es in dem Verzeichnung und im Verzeichnis /etc/nginx/sites-enabled ist wie im Beispiel der Link auf diese Datei. Habt Ihr eine Idee warum das nicht funktioniert?

Wie würde die Konfiguration für ein Bottle-Projekt aussehen - statt index.html einfach das Python-Bottleprojekt (*.py) angeben? Oder braucht man dann dafür das gunicorn?

Hat jemand von Euch Erfahrung mit Single-Page Applikationen unter Python? Mich würde interessieren, wie das Aktualisieren von Datenbankeinträgen funktioniert (also statt eines Formular-submits die Daten über eine Route an die Bottle-Applikation übergibt, ohne die Seite neu aufzubauen)...

Viele Grüße,
dd0815
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Und Dein Server hat den Hostnamen `mserp` bzw. `www.mserp`?

Nginx ist ein Reverse-Proxy. Um also Deinen Python-Server daran anzuschließen brauchst Du einen Server, z.b. gunicorn.

Single-Page hat ja erstmal nichts mit Python zu tun. Die Anfragen kommen vom Client ganz normal per POST, als ob da jemand ein Formular absenden würde. Nur auf der Client-Seite gibt es kein Formular, sondern die POST-Requests werden per Javascript angestoßen.
Benutzeravatar
noisefloor
User
Beiträge: 3855
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Wie würde die Konfiguration für ein Bottle-Projekt aussehen - statt index.html einfach das Python-Bottleprojekt (*.py) angeben? Oder braucht man dann dafür das gunicorn?
Ja, braucht man.

Wie Siruis3 sagte: nginx ist nur der Reverse Proxy, der eine location an eine auf localhost laufende Instanz von Gunicorn leitet. Gunicorn wiederum liefert die eigentlich Applikation aus. Dazu bindest du die app-Instanz aus deiner Bottle-Applikation an Gunicorn.

Wie gesagt: klingt kompliziert, ist es aber nicht. BTW: das funktioniert mit Flask vom Prinzip genau so. Wenn du also Beispiele für Flask findest, kannst du das auf Bottle übertragen.

Warum testest du das ganze nicht auch einem normalen Desktop-Rechner mit Ubuntu 18.04? Funktioniert genau so gut und du brauchst keinen eigenen Server.

Gruß, noisefloor
dd0815
User
Beiträge: 33
Registriert: Donnerstag 25. Juli 2019, 13:57

Hallo Sirius3 & noisefloor,

die Applikation soll nicht im Internet laufen, sondern nur im Firmennetzwerk (weswegen ich mit der Beispieldomain www.example.com so durcheinanderkomme). D.h. im Browser möchte ich dann entweder direkt die IP meines internen Servers "a.b.c.d/mserp" oder via DNS "SRMS004/mserp" angeben. Die Web-Applikation soll später mal den Zugriff auf verschiedene Firmen-Dienste (einzelne Python- oder PHP-Skripte) ermöglichen sowie Firmen-Informationen aus mehreren Quellen bündeln, weshalb ich das alles gleich auf einem Server zum Laufen bringen möchte.

Habe nun gunicorn installiert und bin grade im Netz auf der Suche nach einer guten Anleitung um nginx, gunicorn und bottle zusammen zum Funktionieren zu bekommen - um Euch nicht immer nach jedem Detail fragen zu müssen :D ...

Wenn das läuft probiere ich das mit dem Starten des Datenbank-Updates per Javascript...

Viele Grüße,
dd0815
dd0815
User
Beiträge: 33
Registriert: Donnerstag 25. Juli 2019, 13:57

Hallo nochmal,

ich hab meine Erkenntnisse mal zusammengefaßt (hoffentlich gehts so mit dem Bild):

Bild
https://img1.img1.de/Firma96640.jpg

1) Ich habs immer noch nicht hinbekommen, dass nginx mir eine einfache index.html in diesem Serverblock ausliefert...

Code: Alles auswählen

server {
        listen 80;
        listen [::]:80;

        server_name mserp;

        root /var/www/mserp;
        index index.html;

        location / {
                try_files $uri $uri/ =404;
        }
}

Hab im root schon alle Varianten mit/ohne Verzeichnis html durch, immer noch findet nginx nichts:
172.21.6.18 - - [01/Oct/2019:10:14:33 +0000] "GET /mserp HTTP/1.1" 404 152 "-" " Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0"
Aber mehr als diese Datei erstellen und den Symlink in sites-enabled muss ich doch nicht machen, oder?

2) Ich hab noch nichts Verwertbares gefunden, wie ich meine Applikation im gunicorn starten muss, nur das:

Code: Alles auswählen

gunicorn -w 4 hello_bottle:app
Wobei ich nicht weiß, was in diesem Beispiel hello_bottle ist, ein Dateiname oder irgendein Objekt in meiner Applikation. Muss ich da sonst noch etwas konfigurieren?

So langsam verlässt mich wieder die Motivation :cry:

Viele Grüße,
dd0815
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn du auf einen Pfad mit /mserp zugreifst, dann muss da auch was sein. Ist da was? Denn die Konfiguration setzt ja erstmal etwas ab / auf. Liegt da eine index.html?

Und hello_bottle ist ein Modul, app das Anwendungsobjekt darin, das von gunicorn bedient werden soll.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Und nochmal die Frage: die DNS-Auflösung Deines Servers ergibt `mserp`? Weiter oben hast Du was von `SRMS004` geschrieben. Lösch mal die Zeile raus, denn Du brauchst sie ja wahrscheinlich nicht.
dd0815
User
Beiträge: 33
Registriert: Donnerstag 25. Juli 2019, 13:57

So sieht mein /var/www-Verzeichnis aus, die Index.html habe ich wie gesagt testweise in einem html-Verzeichnis und direkt im mserp-Verzeichnis gelassen und das root mal ins mserp/html-Verzeichnis schauen lassen und mal nicht... Wie gesagt der default-Pfad funktioniert und ich hab alles genauso wie bei diesem gemacht :cry:

Code: Alles auswählen

[
├── html
│   └── index.nginx-debian.html
└── mserp
    ├── html
    │   └── index.html
    └── index.html
Mein Test-Server hat die interne IP 172.21.3.4 sowie den Namen SRMS004. Wenn ich beides in die Adresszeile des Browsers eingebe, sehe ich die Standard-Nginx-Seite (im Tree die index.nginx-debian.html). Aber sowohl bei 172.21.3.4/mserp und SRMS004/mserp findet er wie beschrieben nichts... Wie oben beschrieben würde ich gern die Applikation so erreichen. Oder hab ich noch irgendwo einen Denkfehler und die Serverblock-Konfiguration muss dafür anders aussehen? :?

Die Tree-Formattierung hat es zerhauen, das untere html-Verzeichnis ist ein Unterverzeichnis vom mserp
dd0815
User
Beiträge: 33
Registriert: Donnerstag 25. Juli 2019, 13:57

Oder hat das mal wieder etwas mit Rechten zu tun?
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Also, in der Config-Datei steht `server_name mserp;`, der Block gilt also nur für Anfragen, die genau an diesen Host (mserp) gerichtet werden, nicht SRMS004 oder sonstwas.
`root /var/www/mserp;` bedeutet, dass alles relativ zum Pfad /var/www/mserp gesucht wird, im Browser /mserp bedeutet also entweder /var/www/mserp/mserp oder wegen Index /var/www/mserp/mserp/index.html
Keine der beide Dateien existiert.
dd0815
User
Beiträge: 33
Registriert: Donnerstag 25. Juli 2019, 13:57

Ok, die Funktionsweise der Serverblöcke verstehe ich nun definitiv nicht mehr.

Wenn ich in der Browser-Adresszeile irgendetwas eingebe, z.B. http://www.google.de, dann wird erstmal eine Anfrage an unseren internen DNS-Server gemacht, damit er google.de in eine IP auflösen kann. Nun weiß unser DNS-Server natürlich nicht, dass ich mit mserp nicht irgendetwas im Internet meine, sondern etwas auf dem Server SRMS004. Daher muss ich ja vorn die Server-IP eingeben, die nicht aufgelöst werden muss. Das funktioniert bei anderen Webapplikationen bei uns ja auch, bspw. haben wir auf besagtem alten Unbuntu-Server ein Redmine (Projektmanagement) laufen, welches ich unter SRMS507/redmine erreichen kann - Was muss ich denn nun beim Serverblock einstellen, damit ich meine Applikation auch so erreichen kann? Ohne direkte Angabe der IP bzw. des Namens SRMS004 komme ich ja gar nicht auf den Server...

Hm, jetzt habe ich mal den Default-Pfad auf meinen Ordner gesetzt, nginx neu gestartet, aber die Standardseite kommt immer noch...
dd0815
User
Beiträge: 33
Registriert: Donnerstag 25. Juli 2019, 13:57

Habe nun in meiner Konfiguration mal den Port verändert, statt 80 mal die 8080 - das funktioniert. Meine index.html wird unter http://172.21.3.4:8080/ bzw. SRMS004:8080 angezeigt

Und den Servernamen in einen Unterstrich wie im Default...

Ok, kommen wir nun gunicorn...
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

DU HAST NUR EINEN HOST AUF DEINEM SERVER, DIE server_name-ZEILE IST ALSO ÜBERFLÜSSIG UND KANN WEG.
Den Host schickt Dein Browser mit, und zwar anhand dessen, was Du als URL eintippst, bei Dir also SRMS004.

Wenn es verschiedene Anwendungen auf dem selben Host gibt, die über die Pfade unterschieden werden, dann brauchst Du einen reverse-Proxy (also nginx), der die URL parst und je nach erstem Verzeichnis unterschiedliche Anwendungen anspricht.
Antworten