Nginx schreibt auf Docker-Computer neu, wenn Host-Port! = Container-Port

10

Ich versuche, mehrere Docker-Container auszuführen, auf denen alle nginx ausgeführt werden und die Port 80 überwachen, wobei jedoch unterschiedliche Host-Ports dem Container-Port 80 zugeordnet sind.

Zum größten Teil funktioniert dies, außer wenn nginx eine Umleitung durchführt, weil ein abschließender Schrägstrich fehlt.

server {
    listen 80;
    root /var/www;
    index index.html;
    location /docs {}
}

Angesichts der obigen Nginx-Konfiguration und eines Docker-Containers, auf dem der Host-Port 8080 dem Container-Port 80 zugeordnet ist, kann ich localhost: 8080 / docs / via curl ok erhalten:

> GET /docs/ HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
* Server nginx/1.9.5 is not blacklisted
< Server: nginx/1.9.5
< Date: Sat, 28 Nov 2015 17:27:05 GMT
< Content-Type: text/html
< Content-Length: 6431
< Last-Modified: Sat, 28 Nov 2015 17:17:06 GMT
< Connection: keep-alive
< ETag: "5659e192-191f"
< Accept-Ranges: bytes
<
... html page ...

aber wenn ich localhost anfordere: 8080 / docs bekomme ich eine Umleitung zu localhost / docs /

> GET /docs HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
* Server nginx/1.9.5 is not blacklisted
< Server: nginx/1.9.5
< Date: Sat, 28 Nov 2015 17:29:40 GMT
< Content-Type: text/html
< Content-Length: 184
< Location: http://localhost/docs/
< Connection: keep-alive
<
... html redirect page ...

Wie kann ich Nginx dazu bringen, den ursprünglichen Port bei der Umleitung beizubehalten? Ich habe versucht, port_in_redirect und server_name_in_redirect zu betrachten, aber sie haben nicht geholfen.


BEARBEITEN

Basierend auf https://forum.nginx.org/read.php?2,261216,261216#msg-261216 scheint dies derzeit nicht möglich zu sein.

Ibasa
quelle
Schauen Sie sich den Nginx-Proxy- Container an, damit Sie keinen dieser verrückten Port-Junk-Umschreibungen durchführen müssen.
Michael Hampton
Ich möchte nicht wirklich, dass etwas vor diesen Containern balanciert. Ich habe eine Docker-Compose-Datei, die den externen Port basierend auf einer env-Variable festlegt, und die meiste Zeit habe ich diese Datei nur einmal "docker-compose up -d". Aus Testgründen und um an anderen Dingen arbeiten zu können, möchte ich jedoch "PORT = 8080 Docker-Compose -p Test Up-D" ausführen können, um eine ganze Reihe neuer Container zu starten (aufgrund des neuen Projektnamens) ), die einem anderen Host-Port zugeordnet sind.
Ibasa
Ack, bin auch auf dieses Problem gestoßen. Ich denke, ich muss Vanille-Nginx nehmen oder das Zeug auf 8080 auf etwas anderes verschieben.
Ken

Antworten:

2

Die einfachste Lösung besteht darin, die indexDirektive zu entfernen und sich nicht auf explizite oder implizite $uri/Weiterleitungen zu verlassen. Beispielsweise:

server {
  listen 80;
  root /var/www;
  location /docs {
    try_files $uri $uri/index.html =404;
  }
}

Dies ist kein identisches Verhalten, da die Umleitung insgesamt vermieden wird. Wenn Sie eine nachgestellte Schrägstrichumleitung wünschen, wie sie das Indexmodul bietet, ist eine komplexere Lösung erforderlich. Beispielsweise:

server {
  listen 80;
  root /var/www;
  location /docs {
    try_files $uri @redirect;
  }
  location @redirect {
    if ($uri ~* ^(.+)/$) { rewrite ^ $uri/index.html last; }
    if (-d $document_root$uri) { return $scheme://$host:8080$uri/; }
    return 404;
  }
}
Richard Smith
quelle
Wie ich in der Frage sagte, die ich ausprobiert habe, habe ich port_in_redirect off hinzugefügt. Im http-Block wurde das gleiche Ergebnis einer Umleitung zu localhost / docs / versucht, Servername_in_Redirect off hinzuzufügen. auch.
Leitet
@Ibasa Ja, tut mir leid. Zweimal lesen - einmal schreiben. Muss versuchen, sich daran zu erinnern.
Richard Smith
5

Die HTTP-Clients setzen den Port in den Host-Header. Wenn Sie bei der Umleitung den ursprünglichen Wert des Host-Headers verwenden, sollte dieser wie erwartet funktionieren. Ich habe den folgenden Code getestet und scheint genau das zu tun, was Sie angefordert haben:

location ~ ^.*[^/]$ {
    try_files $uri @rewrite;
}
location @rewrite {
    return 302 $scheme://$http_host$uri/;
}

> GET /bla HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 302 Moved Temporarily
< Server: nginx/1.9.7
< Date: Sun, 29 Nov 2015 06:23:35 GMT
< Content-Type: text/html
< Content-Length: 160
< Connection: keep-alive
< Location: http://localhost:8080/bla/
Florin Asăvoaie
quelle
Dies ist technisch die richtige Antwort. Es funktioniert auch mit IPs, z. B. hat eine Anfrage an 127.0.0.1:8000 127.0.0.1:8000 als http_host. Dies liegt daran, dass laut: tools.ietf.org/html/rfc2616#section-14.23 http_host Mehrdeutigkeiten berücksichtigen muss, zu denen ein Port hinzugefügt wird. Wenn Ports weggelassen werden, werden die Standardeinstellungen impliziert (z. B. entweder 80 oder 443). Diese Lösung sollte also die sauberste sein, mit der man arbeiten kann ...
lifeofguenter
0

Folgen Sie einfach dieser einfachen Lösung

location /app {
    alias /usr/share/nginx/html/folder;
    if (-d $request_filename) {
        rewrite [^/]$ $scheme://$http_host$uri/ permanent;
    }
}
imal hasaranga perera
quelle
0

Interessant ... Ich bin genau auf dieses Problem gestoßen und konnte es beheben, wie aus Richard Smiths Antwort hervorgeht :

root /var/www;
location = /docs {
    try_files $uri $uri/ =404;
}

Der einzige Unterschied ist, dass ich nicht spezifiziere index.html?

Geben Sie den Fehlercode an, um eine Umleitungsschleife zu vermeiden.

Ich warte immer noch auf das Feedback von Nginx.

Kevin W Matthews
quelle