Nginx reescrever na máquina docker quando porta host != porta do recipiente

Estou tentando executar vários contêineres do docker, todos executando o nginx listening na porta 80, mas com diferentes portas de host mapeando para a porta 80 dos contêineres.

Na maior parte, isso funciona, exceto quando o nginx faz um redirecionamento devido à falta de uma barra à direita.

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

Dada a configuração nginx acima e um contêiner docker executando-o com a porta host 8080 mapeada para a porta do contêiner 80, posso obter localhost: 8080 / docs / via 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 ...

mas se eu solicitar localhost: 8080 / docs, recebo um redirecionamento para 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 ...

Como posso fazer com que o nginx preserve a porta original ao fazer o redirecionamento? Eu tentei olhar para port_in_redirect e server_name_in_redirect, mas eles não ajudaram.


EDITAR

Baseado em https://forum.nginx.org/read.php?2,261216, 261216#msg-261216 isso não parece possível agora.

Os clientes HTTP colocarão a porta no cabeçalho do Host. Se você usar o valor original do cabeçalho do host ao fazer o redirecionamento, ele deve funcionar conforme o esperado. Testei o seguinte código e parece estar fazendo exatamente o que você solicitou:

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/

A solução mais simples é remover o index directiva e não confiar em explícita ou implícita $uri/ redireccionar. Por exemplo:

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

Este não é um comportamento idêntico, pois evita completamente o redirecionamento. Se você quisesse um redirecionamento de barra à direita como o módulo de índice dá, então uma solução mais complexa é necessária. Por exemplo:

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

Basta seguir esta correção simples

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

Interessante... Encontrei precisamente esse problema e consegui corrigi-lo tanto quanto A resposta de Richard Smith sugerir:

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

A única diferença é que não especifico index.html?

Especifique o código de erro para evitar um loop de redirecionamento.

Ainda aguardando feedback do suporte do nginx.

Acho que isso acontece, pois seu Docker é um tipo de NAT / Proxy para seu contêiner nginx. Para o roteamento entre diferentes informações de adição de porta é necessário.

Para mim, isso foi resolvido, adicione o seguinte ao 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, acabou de encontrar esse problema também. Eu acho que vou ter que ir nginx baunilha ou mover as coisas em 8080 para outra coisa.

Veja o Nginx-proxy container, então você não precisa fazer nenhuma dessas portas insanas reescrevendo lixo.

Eu realmente não quero nada equilibrando na frente desses contêineres. Eu tenho um arquivo docker-compose que define a porta externa com base em um var env, e na maioria das vezes eu apenas “docker-compose up-d” Este arquivo uma vez. No entanto, por motivos de teste e para me permitir trabalhar em outras coisas, quero poder fazer “PORT=8080 docker-compose-p test up-d” para girar um novo conjunto de contêineres (devido ao novo nome do projeto) que são mapeados para uma porta host diferente.