Nginx переписать на док-машине, когда порт хоста! = Порт контейнера

10

Я пытаюсь запустить несколько Docker-контейнеров, все из которых запускают nginx, прослушивая порт 80, но с разными портами хоста, сопоставленными с портом 80 контейнера.

По большей части это работает, за исключением случаев, когда nginx выполняет перенаправление из-за отсутствия завершающего слеша.

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

Учитывая приведенную выше конфигурацию nginx и контейнер докера, на котором он работает с портом хоста 8080, сопоставленным с портом 80 контейнера, я могу получить 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 ...

но если я запрашиваю 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, это сейчас не представляется возможным.

Ibasa
источник
Посмотрите в контейнер nginx-proxy , так что вам не нужно делать ничего из этого безумного переписывания порта.
Майкл Хэмптон
Я действительно не хочу ничего балансирующего перед этими контейнерами. У меня есть файл docker-compose, который устанавливает внешний порт на основе env var, и большую часть времени я просто "docker-compose up -d" этот файл один раз. Однако по причинам тестирования и для того, чтобы позволить мне работать над другими вещами, я хочу иметь возможность сделать «PORT = 8080 docker-compose -p test up -d», чтобы ускорить весь новый набор контейнеров (из-за нового имени проекта ), которые сопоставлены с другим портом хоста.
Ибаса
Ак, просто столкнулся с этой проблемой. Я думаю, мне придется пойти ванильным Nginx или переместить вещи на 8080 к чему-то еще.
Кен

Ответы:

2

Самое простое решение - удалить indexдирективу, а не полагаться на явные или неявные $uri/перенаправления. Например:

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

Это не идентичное поведение, поскольку оно полностью исключает перенаправление. Если вы хотели использовать редирект с косой чертой, как это дает модуль index, тогда требуется более сложное решение. Например:

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;
  }
}
Ричард Смит
источник
Как я уже сказал в вопросе, который я пробовал, я добавил port_in_redirect off; к блоку http, тот же результат перенаправления на localhost / docs /, попытался добавить server_name_in_redirect выключен; также. Все еще перенаправляет на localhost / docs /
Ibasa
@Ibasa Да, прости за это. Читайте дважды - пишите один раз. Надо постараться запомнить это.
Ричард Смит
5

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/
Florin Asăvoaie
источник
Это технически правильный ответ. Он также работает с IP-адресами, например, запрос к 127.0.0.1:8000 будет иметь 127.0.0.1:8000 как http_host. Это связано с тем, что в соответствии с: tools.ietf.org/html/rfc2616#section-14.23 http_host необходимо учитывать неоднозначность, к которой добавляется порт. Если порты не указаны, подразумеваются значения по умолчанию (например, 80 или 443). Так что это решение должно быть самым чистым для работы с ...
lifeofguenter
0

Просто следуйте этому простому исправлению

location /app {
    alias /usr/share/nginx/html/folder;
    if (-d $request_filename) {
        rewrite [^/]$ $scheme://$http_host$uri/ permanent;
    }
}
Имал Хасаранга Перера
источник
0

Интересно ... Я столкнулся именно с этой проблемой и смог ее исправить, как подсказывает ответ Ричарда Смита :

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

Разница лишь в том, что я не уточняю index.html?

Укажите код ошибки, чтобы избежать цикла перенаправления.

Все еще жду отзывов от поддержки nginx.

Кевин Мэттьюс
источник