执行 nginx -t、启动或重新加载Nginx时,如果出现 host not found in upstream,说明配置引用的上游名称在当前解析环境中没有得到可用地址。它不是普通的502响应,因为Nginx可能在接收请求前就无法载入配置。
关键是从Nginx所在的主机、容器或Pod内部验证名称解析。 宿主机能解析,不代表容器里的Nginx也能解析;上游进程正常,也不代表配置中的名称、网络和端口正确。

先确认报错位置和生效配置
先进行只读语法检查并输出完整配置:
sudo nginx -t
sudo nginx -T 2>&1 | grep -nE 'upstream|proxy_pass|fastcgi_pass|grpc_pass|resolver'
错误通常会指出配置文件和行号。注意 nginx -T 会展开include文件,真正生效的上游可能来自 /etc/nginx/conf.d、站点目录或自动生成的配置,而不是刚刚编辑的文件。
再查看服务日志,区分加载阶段解析失败和运行阶段上游连接失败:
sudo journalctl -u nginx -n 100 --no-pager
sudo tail -n 100 /var/log/nginx/error.log
只有日志确实指向名称解析,才应修改DNS或resolver;connection refused、timeout和permission denied属于其他故障链。
在Nginx实际运行环境中测试DNS
主机安装了glibc工具时,可先查询目标名称:
getent ahosts api.internal.example
resolvectl query api.internal.example
cat /etc/resolv.conf
如果Nginx运行在容器中,要在同一个容器里测试,而不是只在宿主机上测试:
docker exec gateway cat /etc/resolv.conf
docker exec gateway getent hosts backend
docker inspect -f '{{json .NetworkSettings.Networks}}' gateway
docker inspect -f '{{json .NetworkSettings.Networks}}' backend
精简镜像可能没有 getent,这不等于DNS失败,可使用镜像已有的解析工具或在同网络的诊断容器中验证。不要为了测试而临时修改生产容器的 1 ,这种改动在重建后会丢失。
分清静态名称与动态解析
配置直接写成 proxy_pass http://backend.example:8080; 时,Nginx通常在读取配置时解析名称。此时DNS暂时不可用或名称尚未注册,就可能让 nginx -t 或reload失败。
动态服务发现需要结合Nginx版本和配置形式设计。官方 resolver 指令用于指定解析服务器,并支持按DNS TTL缓存结果,也可用 valid 覆盖缓存时间。使用变量构造 proxy_pass 时,必须确认resolver、URI拼接和错误处理都正确。
不能只在配置中加一行resolver就假设所有静态upstream都会自动热更新。 对需要地址变化的服务,应明确采用受支持的动态解析方式;对稳定地址,则应保证名称在Nginx加载配置前可解析。
容器编排环境常见的名称问题
在Docker Compose中,服务应加入同一个用户定义网络,并通过服务名或网络别名访问。容器里的 127.0.0.1 指向容器自身,不会自动指向另一个backend容器。
services:
gateway:
networks: [appnet]
backend:
networks: [appnet]
networks:
appnet: {}
Docker用户定义网络通常提供嵌入式DNS;Kubernetes则通过Service名称和集群DNS提供发现。若Nginx早于上游名称注册,单纯设置启动顺序仍不保证应用已经可用,应结合健康检查与重试策略。
服务名、容器名、网络别名和公开域名不是同一概念。 Compose项目名前缀、跨网络隔离或Pod命名变化,都可能让手写名称失效。
按环境配置可信resolver
下面示例仅适用于Nginx容器确实使用Docker嵌入式DNS的场景,127.0.0.11 不能照搬到普通VPS或Kubernetes:
resolver 127.0.0.11 valid=30s ipv6=off;
resolver_timeout 5s;
set $backend "backend:8080";
proxy_pass http://$backend;
普通VPS应使用受控的本地或内网DNS地址。Nginx官方文档特别建议把解析服务器放在可信、受保护的本地网络中,以降低DNS欺骗风险。修改前还要检查使用变量后是否改变了原有URI转发行为。
需要复制同一Nginx版本和网络拓扑时,可在 萤光云 建立隔离测试机;需要验证跨地区私网或DNS延迟时,也可在 LightNode 创建临时节点。不要把生产域名的私有解析记录或访问令牌放入公开测试环境。
修改后的加载与请求验收
先检查语法,只有通过后才平滑加载:
sudo nginx -t
sudo systemctl reload nginx
systemctl is-active nginx
再从客户端请求实际路径,同时观察错误日志:
curl -sS -o /dev/null -D - https://example.com/health
sudo tail -f /var/log/nginx/error.log
若上游地址会变化,还要在可控测试环境中重建或切换上游实例,确认DNS TTL过期后Nginx能取得新地址。验收标准应同时包含配置加载成功、目标名称可解析、业务请求成功、错误日志无解析失败,并且旧地址退出后流量能按预期恢复。
FAQ
为什么宿主机能ping通,Nginx容器仍报错?
容器有独立的网络命名空间和 /etc/resolv.conf。应在Nginx容器或同一容器网络内测试解析与连通性。
把上游域名换成IP就能长期解决吗?
只能作为短时诊断。服务迁移、扩缩容或证书校验可能依赖域名,硬编码IP会引入新的维护风险。
加了resolver为什么仍然在启动时报错?
静态upstream与变量形式的解析时机不同,resolver并不会自动改变所有配置的解析行为。需要结合实际指令、Nginx版本和服务发现方式调整。
温馨提示
DNS故障最容易被宿主机测试误导。始终在Nginx真正运行的网络环境中验证,并先保留一份能够通过 0 的配置,避免reload失败后失去快速回退路径。


