使用Nginx在Docker网络中代理内部端口相同的两个React应用
问题分析与解决建议
核心问题
出现502错误的直接原因是Nginx配置中/app-b的proxy_pass指向了宿主机暴露的端口3001,而非容器内部的端口3000。在Docker同一网络内,容器间通信需使用目标容器的内部监听端口,而非宿主机的端口映射值。
应用B的容器内部实际监听端口是3000,宿主机的3001只是映射到容器3000的外部入口,仅用于宿主机外部访问,不适用于容器间的直接通信。
正确解决方案
1. 修正Nginx配置
修改default.conf中/app-b的proxy_pass为容器内部端口:
server { listen 80; listen [::]:80; server_name localhost; location /app-a { 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_pass http://app-a:3000; } location /app-b { 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_pass http://app-b:3000; # 改为容器内部端口3000 } }
修改后重启Nginx容器生效。
2. 解决React应用的子路径适配问题
即使修复了Nginx代理,React应用可能仍会出现静态资源加载失败的情况(默认假设部署在根路径/)。需在构建React应用时指定PUBLIC_URL:
- 构建应用A时:
PUBLIC_URL=/app-a npm run build - 构建应用B时:
PUBLIC_URL=/app-b npm run build
重新构建并部署两个React应用的Docker镜像,确保静态资源路径自动带上/app-a或/app-b前缀。
3. 确认容器网络归属
确保三个容器(app-a、app-b、nginx)确实处于同一Docker网络中:
docker network inspect <你的网络名称>
检查输出中的Containers字段,确认三个容器都在列表内。若不在,需将容器重新连接到同一网络:
docker network connect <你的网络名称> <容器名称>
为什么临时方案不规范
- 使用
http://my-ip:3001代理:流量会从Nginx容器流出到宿主机,再通过端口映射回到app-b容器,绕开了Docker内部网络,效率更低且不符合容器间通信的最佳实践。 - 为应用B构建不同端口的镜像:完全没必要,Docker的端口映射功能就是为了解决同一宿主机上容器端口冲突的问题,无需修改镜像本身。
内容的提问来源于stack exchange,提问作者Akari Oozora
相关产品推荐
相关产品推荐

