Reescritura de Nginx en la máquina acoplable cuando el puerto del host != puerto de contenedores

Estoy tratando de ejecutar múltiples contenedores docker, todos ejecutando nginx escuchando en el puerto 80, pero con diferentes puertos de host que se asignan al puerto 80 de los contenedores.

En su mayor parte, esto funciona, excepto cuando nginx realiza una redirección debido a la falta de una barra diagonal final.

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

Dada la configuración de nginx anterior y un contenedor de docker que lo ejecuta con el puerto de host 8080 asignado al puerto de contenedor 80, puedo obtener localhost: 8080 / docs / a través de curl ok:

> 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 ...

pero si solicito localhost: 8080 / docs, obtengo una redirección a 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 ...

¿Cómo puedo hacer que nginx conserve el puerto original al hacer la redirección? Intenté mirar port_in_redirect y server_name_in_redirect pero no ayudaron.


EDITAR

Basado en https://forum.nginx.org/read.php?2,261216,261216#msg-261216 esto no parece posible en este momento.

Los clientes HTTP colocarán el puerto en el encabezado del Host. Si utiliza el valor original del encabezado host al realizar la redirección, debería funcionar como se esperaba. Probé el siguiente código y parece estar haciendo exactamente lo que solicitó:

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/

La solución más sencilla es eliminar el index directiva y no basarse en información explícita o implícita $uri/ redirigir. Por ejemplo:

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

Este no es un comportamiento idéntico, ya que evita la redirección por completo. Si desea una redirección de barra diagonal final como la que proporciona el módulo index, se requiere una solución más compleja. Por ejemplo:

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;  }}

Solo sigue esta sencilla solución

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

Interesante...... Me encontré precisamente con este problema y pude solucionarlo tanto como Respuesta de Richard Smith sugerir:

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

La única diferencia es que no especifico index.html?

Especifique el código de error para evitar un bucle de redireccionamiento.

Todavía estoy esperando los comentarios del soporte de nginx.

Creo que sucede ya que su Docker es una especie de NAT/Proxy para su contenedor nginx. Para el enrutamiento entre diferentes puertos se requiere información de adición.

Para mí esto se resolvió agregue lo siguiente al nginx.conf

http {    ...    proxy_set_header Host $http_host; # required for docker client's sake    proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;    proxy_set_header X-Forwarded-Proto $scheme;    ...}

Ack, también me encontré con este problema. Supongo que tendré que ir a nginx o mover las cosas en 8080 a otra cosa.

Mire en el [nginx-proxy] (GitHub - nginx-proxy/nginx-proxy: Automated nginx proxy for Docker containers using docker-gen), por lo que no tiene que hacer nada de esta loca reescritura de puertos basura.

Realmente no quiero que nada se balancee frente a estos contenedores. Tengo un archivo docker-compose que establece el puerto externo en función de una var env, y la mayoría de las veces solo “docker-compose up-d” este archivo una vez. Sin embargo, por razones de prueba y para permitirme trabajar en otras cosas, quiero poder hacer “PORT=8080 docker-compose-p test up-d” para activar un conjunto completamente nuevo de contenedores (debido al nuevo nombre del proyecto) que se asignan a un puerto host diferente.