Docker + Nginx Problem?
-
Aktuell sieht meine Nginx-Konfiguration wie folgt aus:
server { listen 80; listen [::]:80; server_name example.com www.example.com; return 301 https://example.com$request_uri; } server { listen 443 ssl; listen [::]:443 ssl; server_name example.com www.example.com; ssl_certificate /home/user/certs/live/example.com/cert.pem; ssl_certificate_key /home/user/certs/live/example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location /api { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } server { listen 80; server_name api.example.com; location / { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_connect_timeout 60s; proxy_read_timeout 120s; } }
# from host system curl 127.0.0.1:8080 curl: (52) Empty reply from server curl -k https://example.com:8080 {"message":"Hello, World!"}
-
Ich habe beim Ausführen von docker nun
0.0.0.0:8080 angegeben und siehe da, es funktioniert.
Leider habe ich nun keine AHnung mehr, was ich egentlich getan habe.
Kann mir das jemand erklären?Ist das ünerhaupt noch sicher?
-
@ravenheart_ggg sagte in Docker + Nginx Problem?:
Aktuell sieht meine Nginx-Konfiguration wie folgt aus:
server { listen 80; listen [::]:80; server_name example.com www.example.com; return 301 https://example.com$request_uri; } server { listen 443 ssl; listen [::]:443 ssl; server_name example.com www.example.com; ssl_certificate /home/user/certs/live/example.com/cert.pem; ssl_certificate_key /home/user/certs/live/example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location /api { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } server { listen 80; server_name api.example.com; location / { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_connect_timeout 60s; proxy_read_timeout 120s; } }
# from host system curl 127.0.0.1:8080 curl: (52) Empty reply from server curl -k https://example.com:8080 {"message":"Hello, World!"}
Deine beiden aufrufe sind unterschiedlich in einem wichtigen Teil.
Einmal https und einmal httpjetzt ich klar was das problem ist. Deine App macht https schon.
Dann hätte auch eincurl -k https://127.0.0.1:8080
funktioniert.
Oder wird bei dir auch {"message":"Hello, World!"} ausgegeben wenn du
curl http://example.com:8080
aufrufst?
-
@ravenheart_ggg sagte in Docker + Nginx Problem?:
Ich habe beim Ausführen von docker nun
0.0.0.0:8080 angegeben und siehe da, es funktioniert.
Leider habe ich nun keine AHnung mehr, was ich egentlich getan habe.
Kann mir das jemand erklären?Ist das ünerhaupt noch sicher?
Dein Problem scheint zu sein, dass du nicht weist über welches protokoll deine App überhaupt daten liefert.
In beiden fällen ist es "gleich" sicher. Egal ob du jetzt über einen proxy gehst oder direkt.
Aber da du über nicht den port angegeben möchtest beim aufruf, brauchst du einen Proxy, da du ja schon einen Webserver auf port 443/80 für andere webseiten laufen hast.
-
Ja und eine "doppelte" ssl Verschlüsselung bringt auch nicht mehr Sicherheit. Es genügt, wenn deine Anwendung http (ohne s) liefert...
Und dann noch ein Rat: Wenn du alles in einem Docker-Compose-File machst, dann hättest du diese Probleme nicht
-
guckt doch einfach mal ins nginx logfile anstatt hier wild rumzuraten. optional mal die logs vom uvicorn container angucken.
wenn du den kram hinter nem TLS termination proxy laufen laesst, fehlt dir der
--proxy-headers
switch fuer uvicorn.
-
@Fragender sagte in Docker + Nginx Problem?:
Ja und eine "doppelte" ssl Verschlüsselung bringt auch nicht mehr Sicherheit. Es genügt, wenn deine Anwendung http (ohne s) liefert...
Sie wäre nicht mal "doppelt" denn die ssl verbindung vom client wird in nginx terminiert und nginx baut eine eigene ssl verbindung zum host auf der in proxy_pass angegeben ist.
In falle von @ravenheart_ggg wäre es dann
Client<---ssl--->Nginx<---ssl--->localhost:8080
-
@firefly sagte in Docker + Nginx Problem?:
In falle von @ravenheart_ggg wäre es dann
Ja, und das muss doch wirklich nicht sein... (das meinte ich (umgangssprachlich) mit doppelt)
-
Ich fasse mal kurz zusammen, wie jetzt alles bei mir läuft und hoffe, dass mir jemand erklärt, warum es läuft und ob es so in Ordnung ist.
Dockerfile-Command:
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080", "--workers", "4"]
Docker-Ausführung (wahrscheinlich wichtigster Teil, da ohne anfangs beschriebene Fehler auftraten:
docker run -d -p 0.0.0.0:8080:8080 -v /home/user/certs:/api/certs:ro myapi:latest
nginx-Konfig:
server { listen 80; listen [::]:80; server_name example.com www.example.com; return 301 https://example.com$request_uri; } server { listen 443 ssl; listen [::]:443 ssl; server_name example.com www.example.com; ssl_certificate /home/user/certs/live/example.com/cert.pem; ssl_certificate_key /home/user/certs/live/example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location /api { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } server { listen 80; listen [::]:80; server_name api.example.com; return 301 https://api.example.com$request_uri; } server { listen 443 ssl; listen [::]:443 ssl; server_name api.example.com; ssl_certificate /home/user/certs/live/example.com/cert.pem; ssl_certificate_key /home/user/certs/live/example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } }
-
@Cardiac sagte in Docker + Nginx Problem?:
wenn du den kram hinter nem TLS termination proxy laufen laesst, fehlt dir der --proxy-headers switch fuer uvicorn
In ordnung ist das nicht, es sei denn du willst uvicorn als prod server benutzen.
Dockerfile
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--proxy-headers", "--port", "8080", "--workers", "4"]
docker run
docker run -d -p 127.0.0.1:8080:8080 -v /home/user/certs:/api/certs:ro myapi:latest
deine nginx conf sieht sofern ich das sehe in ordnung aus, abgesehen von
proxy_buffering off
und derConnection "upgrade"
header, welcher entweder"upgrade"
oder""
sein sollte, bei connection close.
Ausserdem sollte upstream nenkeepalive
haben, aber das sind details die mit deinem eigentlichen problem nichts zutun haben.
-
@Cardiac sagte in Docker + Nginx Problem?:
wenn du den kram hinter nem TLS termination proxy laufen laesst, fehlt dir der --proxy-headers switch fuer uvicorn
In ordnung ist das nicht, es sei denn du willst uvicorn als prod server benutzen.
Vielen Dank für das Feedback. Könntest du den Punkt noch etwas ausführlicher erläutern? Ich bin noch relativ unerfahren im Aufsetzen und sehr dankbar über neue Denkanstöße und wann immer ich was dazu lernen kann.
proxy_buffering off
solte raus?Das mit dem Connection habe ich nicht ganz verstanden.
-
docker run -d -p 0.0.0.0:8080:8080
heisst "forward port 8080 from containerX to port 8080 on all interfaces, including WAN and blow a big fat fucking hole into the firewall"mit der konfiguration kannst du uvicorn direkt ueber dein WAN auf port 8080 erreichen und umgehst dabei jeden proxy der dazwischen haengt.
@ravenheart_ggg sagte in Docker + Nginx Problem?:
proxy_buffering off solte raus?
Gehe ich mal stark von aus. RTFM?
@ravenheart_ggg sagte in Docker + Nginx Problem?:
Das mit dem Connection habe ich nicht ganz verstanden.
der
Connection
header is ein nuance, die nur relevanz besitzt wenn du tatsaechlich ein keepalive zum upstream hast. Abgeshen davon ist die directive in deiner konfiguration sinnfrei, denn nginx nimmt by default http 1.1 fuer upstream connections. also gibts da nichts zum upgraden.
-
heisst "forward port 8080 from containerX to port 8080 on all interfaces, including WAN and blow a big fat fucking hole into the firewall" mit der konfiguration kannst du uvicorn direkt ueber dein WAN auf port 8080 erreichen und umgehst dabei jeden proxy der dazwischen haengt.
Ok das klingt nicht so gut. Also muss ich doch eine andere Konfig finden, nehme ich mal stark an.
Was wieder zur Ursprungsfrage mit dem Bad Gateway führt?
-
Ich hatte doch schon geschrieben, wenn er es richtig macht, braucht er gar kein expose port (außer die des Proxys).
-
@ravenheart_ggg sagte in Docker + Nginx Problem?:
Ok das klingt nicht so gut. Also muss ich doch eine andere Konfig finden, nehme ich mal stark an.
Was wieder zur Ursprungsfrage mit dem Bad Gateway führt??
Ich habe dir doch schon gesagt wie du das konfigurieren musst?@Cardiac sagte in Docker + Nginx Problem?:
Dockerfile
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--proxy-headers", "--port", "8080", "--workers", "4"]
docker run
docker run -d -p 127.0.0.1:8080:8080 -v /home/user/certs:/api/certs:ro myapi:latest
@Fragender sagte in Docker + Nginx Problem?:
Ich hatte doch schon geschrieben, wenn er es richtig macht, braucht er gar kein expose port (außer die des Proxys).
das ist quatsch, denn er hat nginx auf dem host laufen, nicht im container.
-
@Cardiac sagte in Docker + Nginx Problem?:
das ist quatsch, denn er hat nginx auf dem host laufen, nicht im container.
deshalb soll er doch auch alles als Container starten... (hatte ich auch geschrieben)
Edit: Aber ich kenne mich mit uvicorn nicht aus... nie verwendet...
-
@Fragender ist halt auch quatsch, denn sobald du mehr als ein compose oder container projekt auf dem host laufen lassen willst, duplizierst du entweder nginx container und darfst dann manuelles load balancing via compose networks machen, oder du klebst halt wieder nen reverse proxy davor (auf dem host - welch wunder) der dann die ganzen einzelnen nginx container reverse proxies proxied.
ist nicht ganz sinnvoll. solange nginx als proxy benutzt wird, und nicht traefik mit auto-discovery ist es 1000x einfacher nginx selbst auf dem docker host laufen zu lassen, und configs fuer jedes compose oder container direkt zu bauen, anstatt das auch in den container zu wurschteln.
hat auch nichts mit (g)uvicorn zutun. ist halt einfach ne eigenschaft des reverse proxies
-
@ravenheart_ggg sagte in Docker + Nginx Problem?:
Ich starte mit
docker run -d -p 8080:8080 -v /home/user/certs:/api/certs:ro myapi:latestJetzt sehe ich das erst. Und das zeigt, dass meine Vermutung vermutlich richtig ist, dass uvicorn schon selbst https macht und nicht http. Denn du gibst informationen über ein ssl zertifikat in den container mit rein (
-v /home/user/certs:/api/certs:ro
)Daher ist die angabe von http:// in der nginx config für proxy_pass natürlich falsch.
Mit den angaben von Cardiac, wie der docker container gestartet werden soll, sollte der proxy_pass part in der nginx config für api.example.com so aussehen:proxy_pass https://127.0.0.1:8080;
Wenn die kommunikation zwischen nginx und uvicorn unverschlüsselt erfolgen soll, so müsstest du uvicorn so umkonfigurieren dass es kein SSL/TLS aktiviert.
-
weia....das hab ich ja voll verrafft. schmeiss dein TLS geraffel von uvicorn einfach weg, lass nginx TLS termination proxy spielen und sprech mit dem upstream http. wie die beiden anderen schon gesagt haben macht es absolut keinen sinn ne neue TLS session zwischen docker host und docker container aufbauen zu lassen.
-
Ich versuche, dem Thread zu folgen und habe nun folgende Anpassungen vorgenommen.
Ich starte docker mit
--ip 172.18.0.2
. Diese IP nutze ich dann zu Starten von uvicorn als auch in nginx.
Weiterhin habe ich das Volume aus Docker rausgeworfen und lasse nginx die Verschlüsselung übernehmen.Kommt das jetzt in Etwa hin?