Nginx przepisuje na maszynie dokującej, gdy port hosta! = Port kontenera

10

Próbuję uruchomić wiele kontenerów dokerów, wszystkie z uruchomionym nasłuchiwaniem nginx na porcie 80, ale z różnymi mapami portów hosta na port 80 kontenerów.

W większości przypadków to działa, z wyjątkiem sytuacji, gdy nginx dokonuje przekierowania z powodu braku końcowego ukośnika.

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

Biorąc pod uwagę powyższą konfigurację nginx i kontener dokujący z uruchomionym portem 8080 hosta zmapowanym do portu 80 kontenera, mogę uzyskać 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 ...

ale jeśli poproszę localhost: 8080 / docs, otrzymam przekierowanie do 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 ...

Jak mogę zmusić nginx do zachowania oryginalnego portu podczas przekierowania? Próbowałem spojrzeć na port_in_redirect i server_name_in_redirect, ale nie pomogły.


EDYTOWAĆ

Na podstawie https://forum.nginx.org/read.php?2,261216,261216#msg-261216 obecnie nie wydaje się to możliwe.

Ibasa
źródło
Zajrzyj do kontenera proxy nginx , abyś nie musiał robić żadnego z tych szalonych przeróbek śmieci.
Michael Hampton
Naprawdę nie chcę niczego równoważącego się przed tymi pojemnikami. Mam plik skompilowania dokera, który ustawia port zewnętrzny na podstawie zmiennej env var, i przez większość czasu po prostu „kompiluję doker-up -d” ten plik raz. Jednak ze względów testowych i aby umożliwić mi pracę nad innymi rzeczami, chcę móc wykonać „PORT = 8080 docker-compose -p test up -d”, aby rozwinąć cały nowy zestaw kontenerów (z powodu nowej nazwy projektu ), które są mapowane na inny port hosta.
Ibasa
Ack, właśnie wpadłem na ten problem. Chyba będę musiał wybrać waniliowy nginx lub przenieść rzeczy na 8080 do czegoś innego.
Ken

Odpowiedzi:

2

Najprostszym rozwiązaniem jest usunięcie indexdyrektywy i nie poleganie na wyraźnych lub dorozumianych $uri/przekierowaniach. Na przykład:

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

To nie jest identyczne zachowanie, ponieważ całkowicie eliminuje przekierowanie. Jeśli chcesz przekierowania ukośnika końcowego, jak daje moduł indeksu, wymagane jest bardziej złożone rozwiązanie. Na przykład:

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
źródło
Jak powiedziałem w pytaniu, którego próbowałem, dodałem port_in_redirect; do bloku http, ten sam wynik przekierowania do localhost / docs /, próbował dodać serwer_nazwa_w_redirect off; także. Nadal przekierowuje do localhost / docs /
Ibasa
@Ibasa Tak, przepraszam za to. Przeczytaj dwa razy - napisz raz. Musisz spróbować to zapamiętać.
Richard Smith
5

Klienci HTTP umieszczą port w nagłówku hosta. Jeśli podczas wykonywania przekierowania użyjesz oryginalnej wartości nagłówka hosta, powinna ona działać zgodnie z oczekiwaniami. Przetestowałem następujący kod i wygląda na to, że robi dokładnie to, o co prosiłeś:

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
źródło
To technicznie poprawna odpowiedź. Działa również z adresami IP, np. Żądanie do 127.0.0.1:8000 będzie miało 127.0.0.1:8000 jako http_host. Jest tak, ponieważ według: tools.ietf.org/html/rfc2616#section-14.23 http_host musi uwzględniać niejednoznaczności, do których doda port. Jeśli porty zostaną pominięte, domyślna wartość domyślna (np. 80 lub 443). To rozwiązanie powinno być najczystsze do pracy z ...
lifeofguenter
0

Postępuj zgodnie z tą prostą poprawką

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

Ciekawe ... Dokładnie napotkałem ten problem i byłem w stanie go naprawić, jak sugeruje odpowiedź Richarda Smitha :

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

Jedyną różnicą jest to, że nie określam index.html?

Podaj kod błędu, aby uniknąć pętli przekierowania.

Wciąż czekam na opinie od wsparcia nginx.

Kevin W. Matthews
źródło