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.


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

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/

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

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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.