Docker环境下Nginx正则location的proxy_pass DNS解析异常原因咨询
这本质是Nginx对两种location类型的proxy_pass采用了完全不同的DNS解析策略:
1. 普通前缀location的静态解析逻辑
当使用不带正则的前缀location(比如location /images/)时,Nginx会在启动或重载配置阶段就完成proxy_pass中域名的DNS解析,把域名转换成对应的IP地址并缓存起来。这个阶段Nginx会直接使用系统默认的DNS配置完成解析,所以不需要手动指定resolver,后续所有请求都会直接用缓存的IP转发。
你的第一个配置就属于这种情况:
location /images/ { proxy_pass http://sfs-filer:8888; proxy_set_header Host $host; }
2. 正则location的动态解析逻辑
当使用正则location(比如location ~ (...))且proxy_pass中包含变量(这里的$1就是正则捕获的变量)时,Nginx会把这个proxy_pass判定为动态配置。它不会在启动阶段解析域名,而是每次请求到达时才会尝试解析域名。
这种情况下,Nginx不会默认使用系统DNS,必须手动通过resolver指令指定DNS服务器,否则Nginx不知道该用哪个DNS去做实时解析,就会抛出如下错误:
[error] 29#29: *442 no resolver defined to resolve sfs-filer, client:
172.18.0.1, server: , request: "GET /9395123a-39bd-4951-acd9-e759fae2e7f4.webp HTTP/1.1", host:
"localhost"
你的第二个配置中,proxy_pass http://sfs-filer:8888/$1里的$1触发了动态解析逻辑,即使域名和第一个配置完全一样,也必须指定resolver:
location ~ ([a-zA-Z0-9-]+\.(jpg|jpeg|png|gif|webp|bmp|avif))$ { proxy_pass http://sfs-filer:8888/$1; proxy_set_header Host $host; }
为什么添加resolver后就正常了?
resolver 127.0.0.11 valid=10s;指定了Nginx用于动态解析的DNS服务器(127.0.0.11是Docker环境下常用的内置DNS),同时valid=10s设置了解析结果的缓存时间,避免每次请求都去查询DNS,既解决了解析源的问题,又保证了性能。
内容的提问来源于stack exchange,提问作者padavan

