Docker + Nginx Problem?



  • was sagt

    netstat -tulpen
    

    ?

    Vermutlich binded docker den port nicht an 0.0.0.0 (generic für alle network devices) sondern an eine der IP-Addressen (und nicht des lcoalhost aka loopback aka 127.0.0.1) des hosts.

    Damit es mit localhost oder besser 127.0.0.1 funktioniert müsste es ausreichen den start des docker containers wie folgt zu ändern:

    docker run -d -p 127.0.0.1:8080:8080 -v /home/user/certs:/api/certs:ro myapi:latest
    

    Dadurch sagst du docker den port explizit an die ip-addresse des loopback devices zu binden.
    Dadurch ist via 8080 die app nicht mehr von außen erreichbar aber du kannst dann in der proxy configuration dann http://127.0.0.1 nutzen



  • docker run -d -p 127.0.0.1:8080:8080 -v /home/user/certs:/api/certs:ro myapi:latest
    

    Immer noch Bad Gateway 😞

    netstat:

    tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      0          3830253092 -                   
    tcp        0      0 0.0.0.0:8880            0.0.0.0:*               LISTEN      0          4121481349 -
    

    lsof:

    COMMAND      PID USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
    docker-pr 473846 root    4u  IPv4 3830253092      0t0  TCP localhost:http-alt (LISTEN)
    


  • Generell sollte man aber Expose Port to Host ganz vermeiden, und nur für die Testzwecke verwenden.

    Also, um das schrittweise auszuprobieren, wie es funktioniert, ist das ok. Hinterher dann (in Production) sollte man aber vermeiden.



  • @ravenheart_ggg mach doch mal sudo netstat -tlpn, um sehen zu können, was dort läuft.



  • netstat:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      474475/docker-proxy 
    tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      473972/nginx: maste 
    tcp        0      0 0.0.0.0:8880            0.0.0.0:*               LISTEN      104772/sw-cp-server 
    tcp        0      0 0.0.0.0:465             0.0.0.0:*               LISTEN      992/master          
    tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      1081/systemd-resolv 
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      761/sshd: /usr/sbin 
    tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN      992/master          
    tcp        0      0 127.0.0.1:12346         0.0.0.0:*               LISTEN      992/master          
    tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      473972/nginx: maste 
    tcp        0      0 0.0.0.0:8443            0.0.0.0:*               LISTEN      104772/sw-cp-server 
    tcp        0      0 0.0.0.0:4190            0.0.0.0:*               LISTEN      105385/dovecot      
    tcp        0      0 127.0.0.1:12768         0.0.0.0:*               LISTEN      106105/psa-pc-remot 
    tcp        0      0 0.0.0.0:993             0.0.0.0:*               LISTEN      105385/dovecot      
    tcp        0      0 0.0.0.0:995             0.0.0.0:*               LISTEN      105385/dovecot      
    tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      1035/mariadbd       
    tcp        0      0 0.0.0.0:110             0.0.0.0:*               LISTEN      105385/dovecot      
    tcp        0      0 0.0.0.0:143             0.0.0.0:*               LISTEN      105385/dovecot      
    tcp6       0      0 :::80                   :::*                    LISTEN      473972/nginx: maste 
    tcp6       0      0 :::8880                 :::*                    LISTEN      104772/sw-cp-server 
    tcp6       0      0 :::8081                 :::*                    LISTEN      447849/apache2      
    tcp6       0      0 :::465                  :::*                    LISTEN      992/master          
    tcp6       0      0 :::21                   :::*                    LISTEN      776/xinetd          
    tcp6       0      0 :::22                   :::*                    LISTEN      761/sshd: /usr/sbin 
    tcp6       0      0 :::25                   :::*                    LISTEN      992/master          
    tcp6       0      0 :::443                  :::*                    LISTEN      473972/nginx: maste 
    tcp6       0      0 :::8443                 :::*                    LISTEN      104772/sw-cp-server 
    tcp6       0      0 :::4190                 :::*                    LISTEN      105385/dovecot      
    tcp6       0      0 :::993                  :::*                    LISTEN      105385/dovecot      
    tcp6       0      0 :::995                  :::*                    LISTEN      105385/dovecot      
    tcp6       0      0 :::106                  :::*                    LISTEN      776/xinetd          
    tcp6       0      0 :::110                  :::*                    LISTEN      105385/dovecot      
    tcp6       0      0 :::143                  :::*                    LISTEN      105385/dovecot
    


  • docker ps und danach docker inspect <container ID> mal aufrufen, das sollte auch einige Informationen liefern.

    und proxy_pass http://127.0.0.1:8080; würde auch nicht funktionieren?



  • @Fragender sagte in Docker + Nginx Problem?:

    Generell sollte man aber Expose Port to Host ganz vermeiden, und nur für die Testzwecke verwenden.

    Also, um das schrittweise auszuprobieren, wie es funktioniert, ist das ok. Hinterher dann (in Production) sollte man aber vermeiden.

    Ich sehe kein Problem einen Port auf localhost zu exposen?



  • @ravenheart_ggg sagte in Docker + Nginx Problem?:

    docker run -d -p 127.0.0.1:8080:8080 -v /home/user/certs:/api/certs:ro myapi:latest
    

    Immer noch Bad Gateway 😞

    netstat:

    tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      0          3830253092 -                   
    tcp        0      0 0.0.0.0:8880            0.0.0.0:*               LISTEN      0          4121481349 -
    

    lsof:

    COMMAND      PID USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
    docker-pr 473846 root    4u  IPv4 3830253092      0t0  TCP localhost:http-alt (LISTEN)
    

    Öhm und wie sieht deine nginx configuration aus?
    Und hast du überhaupt mal lokal getestet ob ein request an http://127.0.0.1:8080 das gewünschte zurückliefert?



  • @firefly

    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?:

    @firefly

    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 http

    jetzt ich klar was das problem ist. Deine App macht https schon.
    Dann hätte auch ein

    curl -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 der Connection "upgrade" header, welcher entweder "upgrade" oder "" sein sollte, bei connection close.
    Ausserdem sollte upstream nen keepalive 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.


Anmelden zum Antworten