601 字
3 分钟
OpenResty + Docker 容器重建后出现 502 的原因与解决方案
在使用 OpenResty(基于 Nginx)作为网关,反向代理到 Docker 容器内服务时,常见一个问题:
容器重启或更新后,OpenResty 返回 502 Bad Gateway。
本文将从现象入手,分析原因,并给出最佳配置实践。
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-15.2 接口可用性测试
docker exec -it openresty_container curl http://doamin.com/api/health6. Docker 网络建议
确保容器处于同一网络,例如:
networks: net: driver: bridge
services: gateway: image: openresty networks: - net
backend: image: your-backend-image networks: - net7. 总结
| 问题 | 解决方式 |
|---|---|
| 容器更新导致服务 IP 变化 | 使用 Docker 内置 DNS 动态解析 |
| Nginx 默认缓存域名 IP 不变 | 使用 resolver + 变量方式实现请求级别动态解析 |
| proxy_pass 无法解析新 IP | 改写为 set $backend_host http://服务名; proxy_pass $backend_host; |
8. 参考资料
OpenResty + Docker 容器重建后出现 502 的原因与解决方案
https://blog.martinpu.cn/posts/ops/openresty-docker-502-fix/