You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
    

验证操作

  1. 重启本地Nginx:sudo systemctl restart nginx
  2. 重启Docker容器:docker restart <container-name>
  3. 清空浏览器缓存(尤其是HSTS缓存)后,访问target-green.domain.example

内容的提问来源于stack exchange,提问作者Victor Ponomarenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 16:46:15