OpenResty + Docker 容器重建后出现 502 的原因与解决方案
在使用 OpenResty(基于 Nginx)作为网关,反向代理到 Docker 容器内服务时,常见一个问题:
本文将从现象入手,分析原因,并给出最佳配置实践。
1. 问题描述
示例配置如下:
location /api/ {
proxy_pass http://backend-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;
}
其中 backend-1
是通过 Docker Compose 启动的服务名。
容器更新后出现如下错误:
502 Bad Gateway
日志输出可能如下:
"GET /api/login HTTP/1.1" 502 ...
2. 问题原因分析
2.1 Nginx 默认行为
默认情况下,
proxy_pass http://backend-1/;
中的域名backend-1
会在 Nginx 启动时解析一次然后 Nginx 会缓存解析结果(即 IP 地址) ,后续请求都使用该 IP,不再重新解析。
2.2 Docker 容器 IP 动态变化
Docker Compose 启动的容器每次重建时,IP 地址可能变化;
虽然服务名不变,但 IP 已失效; = Nginx 此时依然连接旧 IP,因此返回 502;
3. 正确解决方案:变量 + resolver 联用
仅使用 resolver 127.0.0.11;
并不能使 Nginx 自动重新解析 proxy_pass
中的静态域名。 要实现 每次请求动态解析域名 ,你需要将 proxy_pass
改写为变量形式:
set $backend_host http://backend-1;
proxy_pass $backend_host;
同时,在 http 区块中添加:
resolver 127.0.0.11 valid=10s;
解释如下:
使用变量触发每次请求时的动态域名解析;
127.0.0.11
是 Docker 的内置 DNS 服务器;valid=10s
表示每 10 秒重新解析一次域名。
4. 完整示例配置
http {
resolver 127.0.0.11 valid=10s;
server {
listen 1010;
server_name localhost;
location /api/ {
set $backend_host http://backend-1;
proxy_pass $backend_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /desktop/ {
proxy_pass http://192.168.0.80:4010/desktop/;
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 Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
}
location / {
proxy_pass http://192.168.0.80:4020/;
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 Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
}
}
}
5. 验证方式
5.1 DNS 解析测试
docker exec -it openresty_container ping backend-1
5.2 接口可用性测试
docker exec -it openresty_container curl http://doamin.com/api/health
6. Docker 网络建议
确保容器处于同一网络,例如:
networks:
net:
driver: bridge
services:
gateway:
image: openresty
networks:
- net
backend:
image: your-backend-image
networks:
- net
7. 总结
问题 | 解决方式 |
---|---|
容器更新导致服务 IP 变化 | 使用 Docker 内置 DNS 动态解析 |
Nginx 默认缓存域名 IP 不变 | 使用 |
proxy_pass 无法解析新 IP | 改写为 |
8. 参考资料
Last modified: 13 March 2025