多分支环境下Nginx反向代理虚拟主机配置问题求助
我来帮你搞定这个Nginx反向代理+Docker容器的虚拟主机配置问题,之前我在部署多分支前端和服务的时候也踩过不少坑,咱们一步步把问题捋顺,实现你想要的效果——让不同子域名的请求精准转发到对应Docker容器,还能轻松扩展未来新增的服务。
核心思路梳理
咱们的核心目标是:用一个独立的Nginx代理容器作为入口,通过**虚拟主机(子域名)**区分不同请求,转发到同一个Docker网络内的对应容器。这里的关键是Docker容器之间的网络通信(必须在同一个网络才能用容器名访问),以及Nginx的虚拟主机规则配置。
步骤1:搭建Docker自定义网络
默认的Docker bridge网络有局限性,容器之间只能用IP访问,不够灵活。咱们创建一个自定义网桥,这样所有容器都可以用容器名/服务名互相访问,不用依赖动态变化的IP:
docker network create proxy-net
后续所有需要被代理的容器(前端分支容器、Jenkins容器、Nginx代理容器本身)都要加入这个网络。
步骤2:配置Nginx代理的核心规则
直接给你能落地的nginx.conf配置片段,我会逐段解释关键点:
http { # 开启日志,方便排查问题 access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; # -------------------------- # 动态分支前端的虚拟主机配置 # -------------------------- server { listen 80; # 用正则捕获子域名里的分支名,比如 feature1.a.xyz.com 会捕获到 "feature1" server_name ~^(?<branch>.+)\.a\.xyz\.com$; location / { # 直接转发到对应容器:容器名要和你启动的前端分支容器一致(比如 frontend-feature1) proxy_pass http://frontend-$branch:80; # 必须设置这些请求头!不然后端容器(尤其是带Nginx层的前端)会拿到错误的Host头,导致路由/页面404 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固定子域名的配置 # -------------------------- server { listen 80; server_name some-jenkins.xyz.com; location / { proxy_pass http://some-jenkins:8080; # 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需要额外支持WebSocket(用于控制台输出),必须加这两行 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } } events { worker_connections 1024; }
关键配置解释:
- 正则server_name:用
~^(?<branch>.+)\.a\.xyz\.com$捕获分支名,这样你新增任何分支(比如dev、feature2),只要启动容器名是frontend-dev、frontend-feature2,dev.a.xyz.com、feature2.a.xyz.com就会自动转发到对应容器,不用改Nginx配置! - proxy_pass的灵活性:如果不想提前定义
upstream(你之前的配置里写了upstream),直接用http://容器名:端口更简单,适合动态分支场景;如果是固定服务(比如Jenkins),可以提前定义upstream,但上面的写法已经足够用。 - 请求头必须设置:尤其是
Host头,带Nginx层的前端容器会根据Host头匹配server_name,如果没传对,前端路由会直接404。
步骤3:启动容器并接入网络
把所有容器都加入咱们创建的proxy-net网络:
- 启动前端分支容器(比如分支名为
dev):
docker run -d --name frontend-dev --network proxy-net your-frontend-image:dev
- 启动Jenkins容器:
docker run -d --name some-jenkins --network proxy-net jenkins/jenkins:lts
- 启动Nginx代理容器(挂载你的配置文件):
docker run -d --name nginx-proxy -p 80:80 -p 443:443 --network proxy-net -v /本地路径/nginx.conf:/etc/nginx/nginx.conf nginx:alpine
注意:如果需要HTTPS,只需要在Nginx里新增443端口的server块,挂载证书文件即可,核心转发逻辑不变。
常见问题排查
如果配置后还是有问题,按这个顺序排查:
- 网络不通:用
docker network inspect proxy-net检查所有容器是否都在这个网络里;进入Nginx代理容器,用ping frontend-dev测试能不能ping通目标容器(ping通说明网络没问题)。 - 虚拟主机不匹配:检查DNS解析,确保子域名(比如
dev.a.xyz.com)指向Nginx代理容器所在的服务器IP;在Nginx容器里执行nginx -t测试配置语法是否正确,重启Nginx:nginx -s reload。 - 后端返回404:检查
proxy_pass的端口是否和容器内部端口匹配(比如前端容器内部Nginx用80,就不要写8080);检查前端容器内部的Nginx配置,确保server_name是_(匹配所有Host),而不是固定的某个域名。 - Jenkins无法访问:检查Jenkins容器的端口是否是8080,或者你有没有修改过Jenkins的内部端口;确保Nginx里的WebSocket配置已经加上。
未来扩展方案
新增容器时,分两种情况:
- 动态分支前端:直接启动容器名符合
frontend-[分支名]的容器,自动匹配[分支名].a.xyz.com,无需修改Nginx配置。 - 固定子域名服务:比如新增
abc.xyz.com对应某个服务,只需要在Nginx里新增一个server块,把server_name设为abc.xyz.com,proxy_pass指向对应容器的容器名:端口即可。
内容的提问来源于stack exchange,提问作者bakowroc




