Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
NGINX在Docker中缓存IP地址并提供错误的内容类型_Docker_Nginx_Dns_Webserver_Openshift - Fatal编程技术网

NGINX在Docker中缓存IP地址并提供错误的内容类型

NGINX在Docker中缓存IP地址并提供错误的内容类型,docker,nginx,dns,webserver,openshift,Docker,Nginx,Dns,Webserver,Openshift,摘要: 我想让NGINX(不是NGINX Plus)使用proxy\u pass中的变量从DNS名称重新解析IP地址(如中所建议)。但当我这样做时,它不会设置/转发正确的内容类型标题,而是始终使用文本/html,用于.css,.js等文件 我的设置: 我有一个前端和一个后端服务运行在单独的Docker容器中(将部署到生产中的OpenShift)。还有第三个容器运行nginx:latest(今天的v1.19.9)并充当反向代理,将对/my app的调用转发到前端,并将对/my app/api的调用

摘要:
我想让NGINX(不是NGINX Plus)使用
proxy\u pass
中的变量从DNS名称重新解析IP地址(如中所建议)。但当我这样做时,它不会设置/转发正确的
内容类型
标题,而是始终使用
文本/html
,用于
.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那样。当我试图让NGINX重新解析DNS名称时,
内容类型的问题就是这样出现的

配置:
以下是我的NGINX配置(仅简化为相关内容):

(请注意
位置/my app{…}
代理通行证末尾的
/
,因为前端是从
/my app
提供服务的,而前端容器本身也是从NGINX提供服务的,直接在
..:8080/
上运行,没有
/my app
上下文路径。我们对后端容器的设置与li相同听
:8000
,但当调用被转发到它时,我们将从它们中删除
/my app
,以便它们直接到达容器中的
..:8000/api

NGINX正在端口
9000
上运行,当我打开http://localhost:9000/my-使用上述尝试1或尝试2的应用程序
.css
.js
、图像文件等都提供
内容类型: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\u pass\u头内容类型
将修复此问题,但这也没有帮助

然后我还学到了“当在proxy_pass中使用变量时,如果指定了URI,它将按原样传递给服务器,替换原始的请求URI。”。这似乎是我在这里遇到的
内容类型问题的一个可能原因

此外,正如您在配置中所看到的,我已将Docker DNS IP设置为:
resolver 127.0.0.11 ipv6=off valid=1s。我还尝试将其设置在
位置
块之外,但同样没有帮助

问题:
那么,如何在NGINX(开源)中重新解析DNS,并设置适当的
内容类型?我没有使用上游服务器,所以我可以摆脱它们,如果这是一个可能的解决方案的一部分的话

p.S.:
正如其他StackOverflow评论中所建议的那样,我不能根据文件夹、文件名等添加单独的
位置
块来“追溯”修复
内容类型
,因为这是一个不断发展的项目,我担心这将需要我定期向NGINX配置添加此类修补程序

编辑:
我发布的配置包含在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;
}

这不是
内容类型的问题。您不正确地使用了
proxy\u pass
。正如你已经指出的那样:

在proxy_pass中使用变量时,如果指定了URI,它将按原样传递给服务器,替换原始请求URI

您当前具有以下工作配置,但希望用变量替换它以强制DNS解析:

location /my-app {
    proxy_pass http://frontend:8080/;
}
最简单的解决方案是使用
rewrite…break
对URI进行更改,并从变量中删除尾随的
/

例如:

location /my-app {
    rewrite ^/my-app/?(.*)$ /$1 break;
    set $frontend_var "frontend:8080";
    proxy_pass http://$frontend_var;
}
location ~ ^/my-app/?(.*)$ {
    proxy_pass http://frontend:8080/$1;
}

或者,使用正则表达式
location
捕获原始请求的其余部分

例如:

location /my-app {
    rewrite ^/my-app/?(.*)$ /$1 break;
    set $frontend_var "frontend:8080";
    proxy_pass http://$frontend_var;
}
location ~ ^/my-app/?(.*)$ {
    proxy_pass http://frontend:8080/$1;
}

这是我最后的工作设置。再次感谢

请注意……:

  • 我没有使用
    上游
    块,因为我正在将它部署到OpenShift。有一个面向POD(~=服务器或容器)的“服务”概念,这基本上就是Nginx中上游的功能
  • 我已经对
    位置
    块进行了重新排序,因此更具体的块,
    /my app/api
    会首先被命中,否则就会失败
  • 我必须添加
    $isargs$args
    部分,否则URL构造不正确,将失败,特别是对我后端的调用
  • 对于OpenShift,我必须在
    代理程序上添加
    .svc.cluster.local
    ,否则解析程序将无法解析服务
这是相关的设置,对于剩余的(默认)Nginx配置,请参阅我在上面的初始问题编辑中发布的配置

index    index.html index.htm;

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;

  # Backend
  location ~ ^/my-app/api/?(.*)$ {
    # Use this for Docker...
    # resolver 127.0.0.11 ipv6=off valid=1s;
    # ... or use this for OpenShift
    # resolver dns-default.openshift-dns.svc.cluster.local ipv6=on 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;

    proxy_pass http://backend.<PROJECT>.svc.cluster.local:8000/api/$1$is_args$args;
  }

  # Frontend
  location ~ ^/my-app/?(.*)$ {
    # Use this for Docker...
    # resolver 127.0.0.11 ipv6=off valid=1s;
    # ... or use this for OpenShift
    # resolver dns-default.openshift-dns.svc.cluster.local ipv6=on 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;

    proxy_pass http://frontend.<PROJECT>.svc.cluster.local:8080/$1$is_args$args;
  }
}
index index.html index.htm;
服务器{
听8080;
root/usr/share/nginx/html;
try_files$uri$args$uri$args/$uri$uri//index.html=404;
重写^/my-app$$scheme://$http\u-host/my-app/permanent;
#后端
位置^/my app/api/?(*)${
#用这个做码头