Ubuntu本地Nginx转发请求至Docker内Nginx时遇重定向过多问题
重定向循环问题排查与解决
问题原因
重定向循环的核心逻辑是:应用app:8891检测到自身运行在HTTP协议环境下,强制跳转到HTTPS版本的target-green.domain.example;而这个跳转请求又会被本地Nginx再次转发到Docker内的Nginx,最终形成无限循环。
具体流转链条:
- 浏览器→本地Nginx(HTTPS 443端口)
- 本地Nginx→Docker内Nginx(HTTPS 445端口,映射容器443)
- Docker内Nginx→
app:8891(HTTP协议) app:8891返回重定向→https://target-green.domain.example- 浏览器重复发起请求,循环往复
另外,本地与Docker内的Nginx同时设置了Strict-Transport-Security头的includeSubdomains参数,加重了浏览器对HTTPS的强制要求,但并非直接诱因。
解决方案
方案1:本地Nginx改用HTTP转发(推荐)
本地到Docker容器的通信属于本机内部网络,无需HTTPS加密,改用HTTP转发可避免SSL层冗余处理,同时让应用正确识别原始请求的协议。
步骤1:调整Docker端口映射
将容器内Nginx的80端口映射到主机445端口(替换原有的443→445映射),示例命令:
docker run -d -p 445:80 <your-nginx-image>
若使用docker-compose,修改ports配置:
ports: - "445:80"
步骤2:修改本地Nginx配置
更新target-green相关的转发规则,改用HTTP协议:
upstream target_green { server 127.0.0.1:445 fail_timeout=0; } server { listen 443 ssl; server_name "target-green.domain.example"; # 保留原有SSL、日志、HSTS等配置不变 location / { proxy_connect_timeout 600; proxy_send_timeout 600; proxy_read_timeout 600; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; # 告诉应用原始请求是HTTPS proxy_pass http://target_green; # 改为HTTP转发 } }
步骤3:修改Docker内Nginx配置
新增监听80端口的server块,处理本地Nginx转发的HTTP请求:
server { set $rootfolder "/var/www/app/"; set $app "http://app:8891"; set $ws "http://app-ws:10000"; # 修复原配置中的笔误:http:/ → http:// listen 80; server_name "target-green.domain.example"; charset utf-8; client_max_body_size 1G; access_log /var/www/app/logs/access.log; error_log /var/www/app/logs/error.log; location / { proxy_connect_timeout 159s; proxy_send_timeout 600; proxy_read_timeout 600; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; # 传递本地Nginx的HTTPS标识 proxy_pass $app; } # 复制原有的/ws/、/static、/media配置到此处 location /ws/ { proxy_pass $ws; proxy_http_version 1.1; proxy_read_timeout 86400; proxy_redirect off; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 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 X-Forwarded-Host $server_name; proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; } location /static { gzip_min_length 1100; gzip_comp_level 3; root $rootfolder/frontend/; } location /media { gzip_min_length 1100; gzip_comp_level 3; root $rootfolder/; } }
注:修复了原Docker配置中http:/app-ws:10000的笔误,改为http://app-ws:10000
方案2:调整应用配置,信任反向代理头
若无法修改Nginx配置,可让应用读取X-Forwarded-Proto头来判断原始请求协议,而非自身的HTTP环境。示例:
- Django:在
settings.py中添加SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') - Express.js:开启反向代理信任
app.set('trust proxy', true);
验证操作
- 重启本地Nginx:
sudo systemctl restart nginx - 重启Docker容器:
docker restart <container-name> - 清空浏览器缓存(尤其是HSTS缓存)后,访问
target-green.domain.example
内容的提问来源于stack exchange,提问作者Victor Ponomarenko
相关产品推荐
相关产品推荐

