Docker Nginx反向代理子路径重定向丢前缀404问题
问题原因
路径前缀丢失由两个配置缺失共同导致:
- Nginx反向代理规则未传递代理相关标准请求头、未重写后端返回的跳转地址,且对无末尾斜杠的子路径访问未做归一化处理
- Jenkins、Grafana默认以域名根路径为部署上下文,未配置子路径挂载参数,生成跳转链接、静态资源路径时默认从根路径起始,不会自动携带服务前缀
修复步骤
1. 配置后端服务的子路径上下文
两个服务都需要显式声明自己被挂载的子路径,才能正确生成内部跳转链接。
修改docker-compose.yml中对应服务的配置,保留原有所有配置不变,新增环境变量段:
Jenkins配置
jenkins: # 此处保留原有build、volumes、ports等所有配置不变 environment: - JENKINS_OPTS=--prefix=/jenkins
Grafana配置
grafana: # 此处保留原有image、volumes、ports等所有配置不变 environment: - GF_SERVER_ROOT_URL=http://myapp.fr/grafana/ - GF_SERVER_SERVE_FROM_SUB_PATH=true
可选优化:如果不需要直接通过宿主机端口访问Jenkins、Grafana,可以删除两个服务下的ports段,仅保留Nginx的端口映射,让后端服务仅在Docker内部网络可达,提升安全性。
2. 修正Nginx反向代理规则
替换原有配置中/jenkins/、/grafana/两个location段的内容,新增无斜杠路径归一化规则、代理头传递、跳转重写、websocket兼容配置:
server { listen 80; listen [::]:80; server_name myapp.fr; #access_log /var/log/nginx/host.access.log main; location / { root /usr/share/nginx/html; index index.html index.htm; } # 无末尾斜杠路径自动归一化,避免匹配不到代理规则 location = /jenkins { return 301 /jenkins/; } location = /grafana { return 301 /grafana/; } location /jenkins/ { # 注意:proxy_pass末尾不要加斜杠,避免前缀被Nginx自动剥离 proxy_pass http://jenkins:8080; 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-Proto $scheme; # 自动重写后端返回的跳转地址,补全/jenkins前缀 proxy_redirect http://$host/ http://$host/jenkins/; proxy_redirect https://$host/ https://$host/jenkins/; # 兼容Jenkins插件、实时日志需要的websocket连接 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; add_header Access-Control-Allow-Origin '*'; } location /grafana/ { # 注意:proxy_pass末尾不要加斜杠,避免前缀被Nginx自动剥离 proxy_pass http://grafana:3000; 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-Proto $scheme; # 自动重写后端返回的跳转地址,补全/grafana前缀 proxy_redirect http://$host/ http://$host/grafana/; proxy_redirect https://$host/ https://$host/grafana/; # 兼容Grafana实时告警、面板推送需要的websocket连接 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; add_header Access-Control-Allow-Origin '*'; } add_header Access-Control-Allow-Origin '*'; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Headers 'User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,Access-Control-Allow-Origin'; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
说明:proxy_pass中直接使用Docker Compose自动解析的服务名jenkins、grafana做后端地址,比自定义hostname更稳定,不需要额外配置DNS解析。
3. 重载配置生效
在docker-compose.yml所在目录执行以下命令,让所有配置生效:
# 重建Jenkins、Grafana容器加载新的环境变量 docker-compose up -d jenkins grafana # 等待10秒让后端服务启动完成后,重载Nginx配置 sleep 10 docker-compose exec web nginx -s reload
验证结果
服务重启完成后:
- 访问
http://myapp.fr/jenkins会自动跳转到http://myapp.fr/jenkins/login?from=%2F,登录、插件管理、任务构建等所有操作的路径都会自动携带/jenkins前缀 - 访问
http://myapp.fr/grafana会自动跳转到http://myapp.fr/grafana/login,看板、告警、数据源配置等所有操作的路径都会自动携带/grafana前缀 - 静态资源加载、接口请求不会出现跨域或404问题
内容的提问来源于stack exchange,提问作者Gati
相关产品推荐
相关产品推荐

