ホストポート!=コンテナポートの場合、DockerマシンでNginxの書き換え


10

ポート80でリッスンするnginxをすべて実行している複数のDockerコンテナーを実行しようとしていますが、コンテナーポート80に異なるホストポートがマッピングされています。

末尾のスラッシュがないためにnginxがリダイレクトを行う場合を除いて、ほとんどの場合これは機能します。

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

上記のnginx構成と、コンテナーポート80にマップされたホストポート8080でそれを実行しているDockerコンテナーを考えると、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-proxyコンテナーを調べて、ジャンクを書き換えるこの非常識なポートを実行する必要がないようにします。
マイケルハンプトン

これらのコンテナの前で何もバランスをとりたくありません。env varに基づいて外部ポートを設定するdocker-composeファイルがあり、ほとんどの場合、このファイルを一度「docker-compose up -d」するだけです。ただし、テスト上の理由と、他の作業を行えるようにするために、「PORT = 8080 docker-compose -p test up -d」を実行して、まったく新しいコンテナセットをスピンアップできるようにしたいと思います(新しいプロジェクト名により) )別のホストポートにマッピングされている。
Ibasa

ああ、ちょうどこの問題にも遭遇しました。私はバニラ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を追加してみました。同じように。
引き続き

@イバサうん、ごめんなさい。2回読み取り-1回書き込み。それを覚えておく必要があります。
Richard Smith、

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/

これは技術的には正しい答えです。これは、例えばへの要求だけでなく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)。したがって、このソリューションは最もクリーンに動作するはずです...
lifeofguenter

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.