我运行了几个带有主机名的docker容器:
web1.本地 web2.本地 web3.本地
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;
}
}
现在,由于容器接收主机名“main”而不是“web1.local”,因此它们无法正确响应请求。
问题:在代理请求时,如何告诉 nginx 在 Host: 标头中传递上游服务器的名称而不是上游服务器组的名称?
答案1
实际上您可以通过 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;
}
}
如您所见,诀窍是创建一个响应特定端口的本地服务器,该服务器将通过重写每个服务器的正确主机来代理服务器。然后,您可以在上游使用此本地服务器,并最终在实际代理中使用该上游。
答案3
虽然这个目标看起来合乎逻辑,nginx 不会更改 Host: 标头来匹配上游。相反,它将upstream
域名视为CNAME
DNS 中的 - 作为获取 IP 地址的一种方式。
在选择上游之前,请求标头(和主体)是固定的。如果发现某个上游无响应,上游可能会在请求中途更改,但请求不会更改。
答案4
因此,通过阅读 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;
}
}