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 解析测试#

Terminal window
docker exec -it openresty_container ping backend-1

5.2 接口可用性测试#

Terminal window
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 不变使用 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/
作者
Lorem Ipsum
发布于
2025-03-13
许可协议
CC BY-NC-SA 4.0