호스트 포트! = 컨테이너 포트 인 경우 도커 시스템에서 Nginx 다시 쓰기


10

포트 80에서 수신 대기하는 nginx를 실행하는 여러 도커 컨테이너를 실행하려고하지만 컨테이너 포트 80에 다른 호스트 포트가 매핑되어 있습니다.

후행 슬래시가 없어서 nginx가 경로 재 지정을 수행하는 경우를 제외하고 대부분의 경우에 작동합니다.

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

위의 nginx 구성과 컨테이너 포트 80에 매핑 된 호스트 포트 8080으로 실행하는 도커 컨테이너를 고려하면 curl ok를 통해 localhost : 8080 / docs /를 얻을 수 있습니다.

> 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 이 지금 할 수있는 권리를 보이지 않는다.


로 봐 의 nginx 프록시 이 미친 포트 재 작성 정크 중 하나를 수행 할 필요가 없습니다, 컨테이너입니다.
Michael Hampton

나는이 컨테이너들 앞에서 균형을 잡기를 원하지 않습니다. env var를 기반으로 외부 포트를 설정하는 docker-compose 파일이 있으며 대부분이 파일을 한 번 "docker-compose up -d"합니다. 그러나 테스트 이유로 다른 일을 할 수있게하려면 "PORT = 8080 docker-compose -p test up -d"를 수행하여 완전히 새로운 컨테이너 세트를 만들 수 있기를 원합니다 (새 프로젝트 이름으로 인해) )가 다른 호스트 포트에 매핑되었습니다.
Ibasa

Ack, 그냥이 문제에 부딪쳤다. 바닐라 nginx로 가거나 8080의 물건을 다른 것으로 옮겨야 할 것 같습니다.
Ken

답변:


2

가장 간단한 해결책은 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;
  }
}

내가 시도한 질문에서 말했듯이 port_in_redirect off를 추가했습니다. localhost / docs /로 리디렉션 한 결과와 동일한 http 블록에 server_name_in_redirect off를 추가하려고 시도했습니다. 게다가. 여전히 localhost / docs /로 리디렉션
Ibasa

@Ibasa 그래, 미안하다. 두 번 읽으십시오-한 번 쓰십시오. 그것을 기억하려고 노력해야한다.
Richard Smith

5

HTTP 클라이언트는 포트를 호스트 헤더에 넣습니다. 리디렉션을 수행 할 때 호스트 헤더의 원래 값을 사용하면 예상대로 작동합니다. 다음 코드를 테스트했으며 요청한대로 정확하게 수행하고 있습니다.

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/

이것은 기술적으로 정답입니다. IP에서도 작동합니다. 예를 들어 127.0.0.1:8000에 대한 요청 은 http_host로 127.0.0.1:8000을 갖습니다. tools.ietf.org/html/rfc2616#section-14.23 에 따르면 http_host 는 포트가 추가 될 모호성을 수용해야합니다. 포트가 빠져 있으면 기본값이 암시됩니다 (예 : 80 또는 443). 따라서이 솔루션은 가장
깨끗하게

0

이 간단한 수정을 따르십시오.

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

0

흥미 롭습니다. 저는이 문제를 정확히 겪었고 Richard Smith의 답변에서 제안한 대로 해결할 수있었습니다 .

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

유일한 차이점은 내가 지정하지 않는다는 것입니다 index.html.

리디렉션 루프를 피하려면 오류 코드를 지정하십시오.

여전히 nginx의 지원으로부터 피드백을 기다리고 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.