Docker环境下使用nginx反向代理
当在 docker 环境下使用 Nginx 作为反向代理和负载均衡到其他容器时,有时需要在我们的堆栈中定义某种启动顺序,因为它们相互依赖。通常情况下需要把后端服务全部启动起来后,再来启动这个 Nginx服务。
首先这种环境循环依赖的问题就不应该存在,退一步来讲,我就部署个几个简单的服务,还要去考虑先有鸡还是先有蛋问题。谁有这功夫,反正我是没有。
上游服务不可用致nginx无法启动
当你先把 nginx 服务启动时,通常会某种原因公示失败,执行检查日志时
docker logs nginx_container
下面类似的消息日志会伴随告诉你:
NameOfService could not be resolved (1: Host not found)
然后,我们nginx配置如下:
upstream upstreamName {
server ghost:2368;
}
server {
listen 80;
server_name demo.vqiu.cn;
return 307 https://$host$request_uri;
}
server {
listen 80;
server_name demo.vqiu.cn;
location / {
proxy_pass http://upstreamName;
proxy_http_version 1.1;
proxy_set_header Host $host;
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;
}
}
动态upstream
从上述得知,当 nginx 反向代理上游服务时,首先这个上游服务能具备能解析,否则nginx无法正常启动。换种说法就是,nginx的proxy_pass指令,因为没有目标,不知道转给谁,然后就抛出异常了。
那么如何解决upstream server启动时不可解析的问题呢?
答案很简单,让DNS告诉nginx上游服务的地址,resolver 指令用起来。
resolver 指令的作用是阻止 nginx 执行代码,如果我无法解析我们要代理的服务器,则不会抛出不可恢复的错误,并将继续尝试解析它直到它可以。
docker 环境的DNS服务一般为:127.0.0.11(这是固定的)
配置参考:
server {
listen 80 reuseport;
server_name demo.vqiu.cn;
location / {
resolver 127.0.0.11 valid=60s ipv6=off;
resolver_timeout 2s;
set $upstream_name ghost;
set $upstream_port 2368;
proxy_pass http://$upstream_name:$upstream_port;
proxy_http_version 1.1;
proxy_set_header Host $host;
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_pass的ip将由resolver来提供,此时无论上游地址是否能正常解析,它也不会去关心这个流程--解析失败直接返回502而已。
重点配置如下:
# ...
resolver 127.0.0.11 valid=60s ipv6=off;
resolver_timeout 2s;
# ...
- valid代表DNS解析地址TTL为60s(即60s后重新发起一次解析)
- resolver_timeout解析超时时间
- 关闭ipv6栈的解析
以上同样适用于kubernetes环境。