Nginx riscrive sulla macchina docker quando porta host! = Porta contenitore


10

Sto cercando di eseguire più contenitori docker che eseguono tutti nginx in ascolto sulla porta 80, ma con diverse porte host associate alla porta 80 dei contenitori.

Per la maggior parte funziona, tranne quando nginx esegue un reindirizzamento a causa della mancanza di una barra finale.

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

Data la precedente configurazione nginx e un contenitore docker che lo esegue con la porta host 8080 mappata sulla porta contenitore 80, posso ottenere 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 ...

ma se richiedo localhost: 8080 / docs ottengo un reindirizzamento 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 ...

Come posso ottenere nginx per preservare la porta originale quando eseguo il reindirizzamento? Ho provato a guardare port_in_redirect e server_name_in_redirect ma non mi hanno aiutato.


MODIFICARE

Basato su https://forum.nginx.org/read.php?2,261216,261216#msg-261216 questo non sembra possibile al momento.


Guarda nel contenitore nginx-proxy , quindi non devi fare nessuna di questa folle spazzatura di riscrittura delle porte.
Michael Hampton,

Non voglio davvero nulla in equilibrio davanti a questi contenitori. Ho un file di composizione docker che imposta la porta esterna in base a un var env, e il più delle volte ho solo "docker-compose up -d" questo file una volta. Tuttavia, per motivi di test e per consentirmi di lavorare su altre cose, voglio essere in grado di fare "PORT = 8080 docker-compose -p test up -d" per creare un nuovo set di container (a causa del nuovo nome del progetto ) associati a una porta host diversa.
Ibasa,

Ack, ho riscontrato anche questo problema. Immagino che dovrò andare alla vaniglia nginx o spostare la roba su 8080 in qualcos'altro.
Ken,

Risposte:


2

La soluzione più semplice è rimuovere la indexdirettiva e non fare affidamento su $uri/reindirizzamenti espliciti o impliciti . Per esempio:

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

Questo comportamento non è identico in quanto evita del tutto il reindirizzamento. Se si desidera un reindirizzamento della barra finale come quello fornito dal modulo indice, è necessaria una soluzione più complessa. Per esempio:

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

Come ho detto nella domanda che ho provato, ho aggiunto port_in_redirect off; al blocco http, stesso risultato di un reindirizzamento a localhost / docs /, ha provato ad aggiungere server_name_in_redirect off; anche. Reindirizza ancora a localhost / docs /
Ibasa il

@Ibasa Sì, mi dispiace per quello. Leggi due volte: scrivi una volta. Deve provare a ricordarlo.
Richard Smith,

5

I client HTTP inseriranno la porta nell'intestazione Host. Se si utilizza il valore originale dell'intestazione host durante il reindirizzamento, dovrebbe funzionare come previsto. Ho testato il seguente codice e sembra che stia facendo esattamente quello che hai richiesto:

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/

Questa è tecnicamente la risposta corretta. Funziona anche con gli IP, ad esempio una richiesta a 127.0.0.1:8000 avrà 127.0.0.1:8000 come http_host. Questo perché in base a: tools.ietf.org/html/rfc2616#section-14.23 http_host deve soddisfare le ambiguità, alle quali verrà aggiunta una porta. Se le porte vengono escluse, sono implicite le impostazioni predefinite (ad es. 80 o 443). Quindi questa soluzione dovrebbe essere la più pulita con cui lavorare ...
lifeofguenter,

0

Segui questa semplice soluzione

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

0

Interessante ... Ho riscontrato esattamente questo problema e sono stato in grado di risolverlo molto come suggerisce la risposta di Richard Smith :

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

L'unica differenza è che non specifico index.html?

Specificare il codice di errore per evitare un ciclo di reindirizzamento.

Ancora in attesa di feedback dal supporto di nginx.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.