Summary:
我想让NGINX(不是NGINX Plus)通过使用变量从DNS名称重新解析IP地址proxy_pass
(如建议的这篇 Nginx 官方文章“在变量中设置域名”部分 https://www.nginx.com/blog/dns-service-discovery-nginx-plus/)。但是当我这样做时,它不会设置/转发正确的Content-Type
标题,但始终使用text/html
, for .css
, .js
等文件。
我的设置:
我有一个前端和一个后端服务在单独的 Docker 容器中运行(将在生产中部署到 OpenShift)。还有第三个容器正在运行nginx:latest
(v1.19.9 截至今天)并充当反向代理,转发对/my-app
到前端和/my-app/api
到后端容器。 NGINX 反向代理已使用其 DNS 名称将它们设置为上游服务器。
所有三个容器都在同一个自定义 Docker 网络中运行,因此解析本身可以正常工作 - 但仅限于(重新)启动 NGINX 时。
问题:
当前端或后端容器重新启动时,它可能会获得新的 IP 地址。由于 NGINX 缓存 IP 地址,我得到了502
当我打电话给他们时。我希望 NGINX 能够更频繁地重新解析 IP 地址,就像 NGINX Plus 那样。这就是问题所在Content-Type
当我尝试让 NGINX 重新解析 DNS 名称时出现了。
配置:
这是我的 NGINX 配置(仅简化为相关内容):
index index.html index.htm;
upstream upstream_frontend {
server frontend:8080;
}
upstream upstream_backend {
server backend:8000;
}
server {
listen 8080;
root /usr/share/nginx/html;
try_files $uri$args $uri$args/ $uri $uri/ /index.html =404;
rewrite ^/my-app$ $scheme://$http_host/my-app/ permanent;
location /my-app {
resolver 127.0.0.11 ipv6=off valid=1s;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_http_version 1.1;
proxy_pass_request_headers on;
proxy_pass_header Content-Type;
# Attempt #1, NOT working: using a variable and an upstream server setup
set $frontend_var "http://upstream_frontend/";
proxy_pass http://$frontend_var;
# Attempt #2, NOT working: using a variable and directly using the container name
# set $frontend_var "http://frontend:8080/";
# proxy_pass $frontend_var;
# Attempt #3, working fine: using NO variable and an upstream server setup, , but no DNS re-resolving happening :-(
# proxy_pass http://upstream_frontend/;
# Attempt #4, working fine: using NO variable and directly using the container name, but no DNS re-resolving happening :-(
# proxy_pass http://frontend:8080/;
}
location /my-app/api {
resolver 127.0.0.11 ipv6=off valid=1s;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_redirect off;
# Attempt #1, NOT working: using a variable and an upstream server setup
set $backend_var "http://upstream_backend/api";
proxy_pass http://$backend_var;
# Attempt #2, NOT working: using a variable and directly using the container name
# set $backend_var "http://backend:8000/api";
# proxy_pass http://$backend_var;
# Attempt #3, working fine: using NO variable and an upstream server setup, , but no DNS re-resolving happening :-(
# proxy_pass http://upstream_backend/api;
# Attempt #4, working fine: using NO variable and directly using the container name, but no DNS re-resolving happening :-(
# proxy_pass http://backend:8000/api;
}
}
(请注意location /my-app {...}
和/
在结束时proxy_pass
,因为前端由/my-app
,而前端容器本身也由 NGINX 提供服务,直接在...:8080/
,没有/my-app
上下文路径。我们对正在监听的后端容器有相同的设置:8000
,但是当呼叫转接到它时,我们将删除/my-app
从他们那里直接到达容器...:8000/api
.)
NGINX 正在端口上运行9000
当我使用上面的内容打开 http://localhost:9000/my-app 时尝试#1 or 尝试#2 the .css
, .js
、图像文件等均由Content-Type: text/html
,这会阻止浏览器正确渲染页面,并在调试器窗格中显示如下消息:
The stylesheet http://localhost:9000/my-app/static/css/main.df1d2133.chunk.css was not loaded because its MIME type, ”text/html“ is not ”text/css"
起初我以为proxy_pass_header Content-Type;
会解决这个问题,但这也没有帮助。
然后我也学到了这个 NGINX 错误单 https://trac.nginx.org/nginx/ticket/1370 that “在 proxy_pass 中使用变量时,如果指定了 URI,则会按原样传递到服务器,替换原始请求 URI。”。这似乎是一个可能的原因Content-Type
我这里有问题。
另外,正如你在配置中看到的,我设置了 Docker DNS IP:resolver 127.0.0.11 ipv6=off valid=1s;
。我也尝试过将其设置在location
阻止,这也没有帮助。
问题:
那么如何在 NGINX(开源)中重新解析 DNSwith正确的Content-Type
还设置吗?我不have使用上游服务器,这样我就可以摆脱它们,这应该是可能修复的一部分。
P.S.:
我不能按照其他 StackOverflow 评论中的建议添加单独的location
阻止“追溯”修复Content-Type
取决于文件夹、文件名等,因为这是一个不断发展的项目,我担心它需要我定期向 NGINX 配置添加此类修补程序。
EDIT:
我发布的配置包含在 NGINX 的 Docker 容器的配置文件中(就是这个),以防您想知道一些“丢失”的设置:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
# This line includes my configuration above
include /etc/nginx/conf.d/*.conf;
}