Nginx在upstream主机不可用或宕机时启动失败的替代方案
Nginx启动时因未启动Docker容器upstream不可用的解决方案
问题根源
默认配置下,Nginx会在启动/重载配置阶段,对静态配置的upstream节点做域名解析与连通性校验,只要有任意节点不可达,就会直接终止启动流程,这是服务器重启后Nginx启动失败的直接原因。
以下是不需要安装第三方模块、配置成本极低的原生处理方案,按推荐优先级排序:
方案1:使用upstream的resolve参数(最适配原有配置)
Nginx开源版原生支持server指令的resolve参数,开启后Nginx不会在启动阶段强制解析对应upstream域名,会在运行周期内通过指定的DNS定期解析节点地址,节点离线/上线都会自动感知,不会阻塞启动流程。
如果使用Nginx 1.25.1以上版本,完全不需要手动指定Docker DNS地址,直接用resolver system配置让Nginx自动读取容器内/etc/resolv.conf的DNS配置即可,不存在IP写错的风险:
http { # 自动读取系统DNS配置,无需手动填写Docker DNS IP resolver system valid=30s ipv6=off; upstream your-service1 { # 加resolve参数,启动时不强制解析该域名 server your-service1-container:8080 resolve; } server { listen 80; server_name service1.yourdomain.com; # 原有其他代理配置完全不需要修改 proxy_pass http://your-service1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
如果Nginx版本低于1.25.1,只要把Nginx和业务容器放在同一个自定义Docker网络下,Docker内置DNS的IP固定为127.0.0.11(Docker官方固定规则,不会变动),把resolver配置改成resolver 127.0.0.11 valid=30s ipv6=off;即可,同样不存在配置错误问题。
方案2:本地兜底backup节点(完全不用修改DNS配置)
如果不想调整resolver相关配置,可以给每个按需启动的upstream加一个本地永远在线的backup兜底节点,Nginx启动时检测到有可用节点就不会报错,业务容器离线时请求自动走到兜底节点返回提示,容器上线后自动切回正常流量,配置改造成本极低。
首先在Nginx里加一个本地兜底的服务监听,不需要额外启动其他进程:
# 本地兜底服务,仅监听本地环回地址 server { listen 127.0.0.1:18080 default_server; return 503 "Service is not started yet, please try again later\n"; add_header Content-Type text/plain; }
然后给对应upstream加backup配置即可:
upstream your-service1 { server your-service1-container:8080 max_fails=1 fail_timeout=10s; # 兜底节点永远在线,标记为backup server 127.0.0.1:18080 backup; } server { listen 80; server_name service1.yourdomain.com; proxy_pass http://your-service1; # 原有其他配置保持不变 }
方案3:变量形式配置proxy_pass(无upstream块场景适用)
如果配置没有单独抽upstream块,直接在server块里写proxy_pass,可以把upstream地址定义为变量,Nginx同样不会在启动阶段解析变量内的域名,只会在实际请求到来时做DNS解析,不会阻塞启动:
server { listen 80; server_name service1.yourdomain.com; resolver system valid=30s ipv6=off; # 低版本换成127.0.0.11 set $upstream_endpoint "http://your-service1-container:8080"; proxy_pass $upstream_endpoint; }
配置注意事项
- 不要使用Docker默认的bridge网络,自行创建自定义bridge/overlay网络把Nginx和所有业务容器加入,既可以直接用容器名做域名访问,也能保证内置DNS地址固定。
valid=30s表示DNS缓存有效期30秒,可根据自己的服务启动频率调整,不建议设置过短增加DNS解析压力。- 以上方案都不需要在容器启动后手动重载Nginx配置,服务上线后Nginx会自动感知节点可用性。
内容的提问来源于stack exchange,提问作者Simon2019
相关产品推荐
相关产品推荐

