Nginx Docker容器配置子路径反向代理多Web应用访问异常排查
配置错误点
- server_name 匹配逻辑错误
你所有监听80端口的server块分别配置了server_name为app1、app2、app3,而浏览器访问的域名是localhost,无法匹配到这几个server_name,Nginx会把请求交给默认server处理(也就是加载顺序第一个的app1.conf的server块),这个块仅配置了/路径的规则,处理不了/app2这类子路径请求,会触发app1的根路径重定向逻辑,最终跳回http://localhost。 - 子路径的proxy_pass未做路径重写
就算请求匹配到了对应子路径的location,你当前的配置是proxy_pass http://app2;,会把完整的请求路径/app2/xxx直接传给后端app2,而app2本身部署在根路径,识别不了/app2前缀,就会触发404或者重定向到根路径。 - 端口配置不匹配
你每个app的容器内部暴露的是80端口(ports配置为8000:80,冒号后为容器内端口),但upstream里写的是server app1:8000,同Docker网络下容器互访需要用容器内端口,此处端口配置错误。 - docker-compose语法错误
你配置文件末尾的networks定义缺少冒号,会导致编排启动失败。
修正方案
1. 调整Nginx配置为单server块
无需拆分多个server块,所有请求走同一个监听localhost的server块即可,新建default.conf配置如下:
upstream app1 { server app1:80; # 修正为容器内端口 } upstream app2 { server app2:80; } upstream app3 { server app3:80; } server { listen 80; server_name localhost; # 匹配访问的localhost域名 # 根路径指向app1 location / { proxy_pass http://app1; 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; } # app2子路径配置 location ^~ /app2/ { # 重写路径,去掉/app2前缀再传给后端 rewrite ^/app2/(.*)$ /$1 break; proxy_pass http://app2; 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; # 修正后端返回的重定向地址,避免跳转到根路径 proxy_redirect ~^/(.*)$ http://$host/app2/$1; } # app3配置和app2同理 location ^~ /app3/ { rewrite ^/app3/(.*)$ /$1 break; proxy_pass http://app3; 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; proxy_redirect ~^/(.*)$ http://$host/app3/$1; } }
2. 修正Nginx挂载配置
删掉原有的多server块配置,只挂载上述统一配置文件即可,无需额外配置sites-available和软链接,避免配置加载混乱,对应docker-compose的volumes调整为:
volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf - ./nginx/nginx.conf:/etc/nginx/nginx.conf
3. 修正docker-compose.yml语法
补全networks定义的冒号,完整修正后的docker-compose.yml如下:
version: "3.8" services: app1: image: app1 image container_name: app1 networks: - local-network ports: - "8000:80" restart: unless-stopped app2: image: app2 image container_name: app2 networks: - local-network ports: - "7000:80" restart: unless-stopped app3: image: app3 image container_name: app3 networks: - local-network ports: - "5000:80" restart: unless-stopped nginx: image: nginx:latest container_name: nginx networks: - local-network command: nginx -g "daemon off;" volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf - ./nginx/nginx.conf:/etc/nginx/nginx.conf ports: - "80:80" restart: unless-stopped depends_on: - app1 - app2 - app3 networks: local-network: # 补全冒号
4. 可选后端配置调整
如果部分后端应用需要感知子路径前缀,可给对应应用配置base path为/app2、/app3,避免应用内生成的跳转链接、静态资源路径指向根路径。
内容的提问来源于stack exchange,提问作者Ruth Mbugua
相关产品推荐
相关产品推荐

