Я пытаюсь запустить несколько контейнеров докеров, все из которых работают с nginx, прослушивающим порт 80, но с сопоставлением разных портов хоста с портом 80 контейнеров.
По большей части это работает, за исключением случаев, когда nginx выполняет перенаправление из-за отсутствия завершающей косой черты.
server {
listen 80;
root /var/www;
index index.html;
location /docs {}
}
Учитывая приведенную выше конфигурацию nginx и контейнер докеров, запускающий его с портом хоста 8080, сопоставленным с портом контейнера 80, я могу получить localhost: 8080 / docs / через 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 ...
но если я запрашиваю localhost: 8080 / docs, я получаю перенаправление на 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 ...
Как я могу заставить nginx сохранить исходный порт при перенаправлении? Я пробовал смотреть на port_in_redirect и server_name_in_redirect, но они не помогли.
РЕДАКТИРОВАТЬ
На основе https://forum.nginx.org/read.php?2,261216,261216#msg-261216 это сейчас не кажется возможным.
HTTP-клиенты помещают порт в заголовок Host. Если вы используете исходное значение заголовка хоста при перенаправлении, оно должно работать должным образом. Я протестировал следующий код и, похоже, выполняет именно то, что вы просили:
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/
Самое простое решение - удалить index
директивы и не полагаться на явные или неявные $uri/
перенаправляет. Например:
server {
listen 80;
root /var/www;
location /docs {
try_files $uri $uri/index.html =404;
}
}
Это не идентичное поведение, поскольку оно полностью исключает перенаправление. Если вам нужно перенаправление в конце косой черты, как в индексном модуле, то требуется более сложное решение. Например:
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;
}
}
Просто следуйте этому простому исправлению
location /app {
alias /usr/share/nginx/html/folder;
if (-d $request_filename) {
rewrite [^/]$ $scheme://$http_host$uri/ permanent;
}
}
Интересно ... Я столкнулся именно с этой проблемой и смог ее исправить как Ответ Ричарда Смита предлагает:
root /var/www;
location = /docs {
try_files $uri $uri/ =404;
}
Единственная разница в том, что я не указываю index.html
?
Укажите код ошибки, чтобы избежать цикла перенаправления.
Все еще ждем отзывов от службы поддержки nginx.
Я думаю, это происходит, потому что ваш Docker является своего рода NAT / прокси для вашего контейнера nginx. Для маршрутизации между разными портами требуется дополнительная информация.
Для меня это было решено добавить следующее в 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;
...
}