Docker Swarm中Nginx反向代理无法获取完整React包的问题
问题排查:Docker Swarm中Nginx反向代理React应用出现响应异常
环境与异常现象
- 部署环境:Docker Swarm工作节点,
nginx:1.22.1与静态React应用服务器绑定同一节点,通过自定义overlay网络通信;Swarm加入时指定数据中心内部地址为advertise address,服务可通过公网访问 - 核心异常:
- 直接公网访问React应用可获取完整资源包,但通过Nginx反向代理时,Chrome浏览器报
net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK),JS包在函数中途被截断 - 偶尔上游服务器返回HTML而非预期的JS包,该响应完整无截断
- 直接公网访问React应用可获取完整资源包,但通过Nginx反向代理时,Chrome浏览器报
Nginx配置文件(/etc/nginx/conf.d/default.conf)
resolver 127.0.0.11 valid=10s; error_log /dev/stdout info; map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; return 301 https://$host$request_uri; } server { listen 443 ssl; ssl_certificate /etc/nginx/certs/nginx.pem; ssl_certificate_key /etc/nginx/certs/key.pem; client_max_body_size 100M; proxy_buffers 8 1024k; proxy_buffer_size 1024k; proxy_max_temp_file_size 1024m; location / { set $reactapp reacthost; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://$reactapp:3000/; proxy_redirect off; } root /usr/share/nginx/html; } error_page 500 502 503 504 /50x.html; }
容器启动日志
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh 10-listen-on-ipv6-by-default.sh: info: can not modify /etc/nginx/conf.d/default.conf (read-only file system?)
已知信息
- 用
$reactapp变量实现Nginx启动后的DNS服务发现 - Nginx以
nginx用户运行,exec进入容器后,该用户可访问/var/cache/nginx/并创建目录 - 此前通过bridge网络部署时,Nginx在上游服务启动后启动,反向代理工作正常;Docker Stack不支持
depends_on,依赖DNS服务发现
怀疑方向
- Nginx服务器/location配置存在语法或逻辑错误
- Stack模式下Nginx无法写入容器所需路径
- overlay网络存在连通性问题,导致上游服务访问异常
排查与解决方法
1. 修复Nginx配置语法错误
当前配置存在明显的语法问题:root /usr/share/nginx/html;的缩进和server块闭合错误,会导致Nginx运行逻辑混乱,是响应异常的核心原因之一。修正后的server块如下:
server { listen 443 ssl; ssl_certificate /etc/nginx/certs/nginx.pem; ssl_certificate_key /etc/nginx/certs/key.pem; client_max_body_size 100M; proxy_buffers 8 1024k; proxy_buffer_size 1024k; proxy_max_temp_file_size 1024m; root /usr/share/nginx/html; location / { set $reactapp reacthost; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; # 使用定义好的变量替代硬编码,适配WebSocket场景 proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://$reactapp:3000/; proxy_redirect off; } error_page 500 502 503 504 /50x.html; }
2. 解决只读文件系统问题
启动日志提示无法修改default.conf,处理方案:
- 在Docker Stack的compose文件中,确认未将
/etc/nginx/conf.d/挂载为只读卷 - 添加环境变量
DISABLE_IPV6=1,禁用10-listen-on-ipv6-by-default.sh脚本,避免其尝试修改配置文件 - 若使用自定义镜像,构建时确保
/etc/nginx/conf.d/目录权限为nginx用户可读写
3. 验证Overlay网络与服务发现
- 进入Nginx容器,执行
nslookup reacthost,确认能正确解析到React应用容器的IP - 多次执行
curl http://reacthost:3000/static/js/main.xxx.js,检查返回内容是否完整、是否偶尔返回HTML,排除上游服务本身的问题 - 在两个容器中互相ping对方的服务名/IP,确认overlay网络连通性稳定
4. 优化Nginx代理缓冲设置
- 添加
proxy_cache_bypass $http_upgrade;,避免WebSocket请求被缓存 - 确保
proxy_buffering on;(默认开启),保证Nginx能正确处理上游返回的chunked编码响应 - 临时设置
proxy_max_temp_file_size 0;,禁止使用临时文件存储响应,排查是否因磁盘写入问题导致截断
5. 替代depends_on确保服务启动顺序
Docker Stack不支持depends_on,可通过以下方式确保React服务先就绪:
- 在Nginx的启动脚本中添加健康检查逻辑,等待
reacthost:3000可访问后再启动Nginx - 在React服务的compose配置中添加
healthcheck,同时在Nginx配置中添加proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;,自动重试未就绪的上游服务
内容的提问来源于stack exchange,提问作者Anthony O
相关产品推荐
相关产品推荐

