ホスト名でいくつかのDockerコンテナーを実行します。
web1.local web2.local web3.local
Nginxによるホスト名に基づいて行われるこれらへのルーティング。このセットアップの前にプロキシがあり(インターネットに接続された別のマシン上)、アップストリームを次のように定義します。
upstream main {
server web1.local:80;
server web2.local:80;
server web3.local:80;
}
そして実際の仮想ホストの説明:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://main;
}
}
現在、コンテナは「web1.local」ではなく「main」というホスト名を受け取るため、リクエストに適切に応答しません。
質問:リクエストをプロキシするときに、Host:ヘッダーで上流のサーバーグループの名前ではなく上流のサーバーの名前を渡すようにnginxに指示するにはどうすればよいですか?
実際には、proxy_set_headerを介してそれを行うことができます。
詳細についてはこちらをご覧ください: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header またはこちらの使用例をご覧ください: https://stackoverflow.com/questions/12847771/configure-nginx-with-proxy-pass
上記の投稿された構成に動的なアプローチを含めました:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://main;
proxy_set_header Host $Host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
以下は、静的ホスト名の例です。
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://main;
proxy_set_header Host www.example.com;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
同じ問題があり、2つのレベルのプロキシを使用して最終的に解決しました。これがあなたの状況にどう対処できるかです(私は思う):
server {
listen 8001 default_server;
server_name web1.example.com;
location / {
proxy_pass http://web1.local:80;
proxy_set_header Host web1.local:80;
}
}
server {
listen 8002 default_server;
server_name web2.example.com;
location / {
proxy_pass http://web2.local:80;
proxy_set_header Host web2.local:80;
}
}
server {
listen 8003 default_server;
server_name web3.example.com;
location / {
proxy_pass http://web3.local:80;
proxy_set_header Host web3.local:80;
}
}
upstream main {
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://main;
}
}
ご覧のとおり、トリックは、各サーバーの適切なホストを書き換えることにより、サーバーをプロキシする特定のポートに応答するローカルサーバーを作成することです。次に、このローカルサーバーをアップストリームで使用し、最後にそのアップストリームを実際のプロキシで使用できます。
したがって、nginxのすべてのドキュメントを読むことから(上流モジュールのコードを実際に解析できなかった=()私はこの粗雑なソリューションを思いつきました。残念ながら、このソリューションは失敗したホストを追跡せず、ランダムなホストを選択してリクエストをリダイレクトします。そのため、すべてのバックエンドが実行されていることを確認するために、何らかの監視をセットアップする必要があります。
server {
listen 80;
server_name example.com;
resolver 127.0.0.1;
location / {
set $upstream "";
rewrite_by_lua '
local upstreams = {
"http://web1.dokku.localdomain",
"http://web2.dokku.localdomain",
"http://web3.dokku.localdomain",
"http://web4.dokku.localdomain"
}
ngx.var.upstream = upstreams[ math.random( #upstreams ) ]
';
proxy_pass $upstream;
}
}
次のように、上流のaddrを個別のヘッダーとして渡します
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://main;
proxy_set_header Host $Host;
proxy_set_header X-Forwarded-For $remote_addr;
add_header X-Upstream $upstream_addr;
}
}
試してみたら?
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://main;
proxy_set_header Host $upstream_addr;
proxy_set_header X-Forwarded-For $remote_addr;
add_header X-Host $Host;
}
}
目標は理にかなっているように見えますが、 nginxはHost:ヘッダーをアップストリームと一致するように変更しません 。代わりに、DNSでupstream
ドメイン名をCNAME
のように扱います-IPアドレスにアクセスする方法として。
要求ヘッダー(および本文)は、アップストリームが選択される前に修正されます。特定のアップストリームが応答しないことが判明した場合、アップストリームは要求の途中で変更される可能性がありますが、要求は変更されません。
うーん。私は同様の設定をしています
location / {
...
proxy_set_header X-Forwarded-Host $http_Host;
proxy_pass ...;
}
の用法 $http_Host
(着信リクエストのHTTPホストヘッダー)ではなく$Host
(サーバーのホスト名の構成)を使用すると、テストでは、クライアントから渡された同じHostヘッダーがアップストリームに渡されます。
https://stackoverflow.com/questions/14352690/change-Host-header-in-nginx-reverse-proxy も参照してください。
他の人々はすでにスクリプト変数($ upstreamなど)を使用して投稿しているので、好きなように設定できます。これにより、追加のヘッダーハッキングなしで問題が修正されます。
値が条件付きでない場合(名前に$が含まれていない場合)プロキシパスハンドラーの脅威スクリプト変数は別の方法で設定フェーズで上流に戻され、後で使用されます。
この問題を省略し、(無料バージョン)アップストリームの最大の利点を得る簡単な方法は、Split_Clients
のようなものを使用することです。
split_clients $request_uri $my_upstream {
33% server1.domainX.com;
33% server2.domainX.com;
# Always use DOT at end entry if you wonder why, read the SC code.
* server3.domainX.com;
}
location / {
...
proxy_pass http://$my_upstream;
}
上記の例は、アップストリームとほとんど同じです。 chash_map_module など、マッピングを行う他のモジュールが存在しますが、それらはツリーの外にあるため、独自に構築する必要があります。これは、一部のユースケースでは不可能です/