You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

多分支环境下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$捕获分支名,这样你新增任何分支(比如devfeature2),只要启动容器名是frontend-devfrontend-feature2dev.a.xyz.comfeature2.a.xyz.com就会自动转发到对应容器,不用改Nginx配置!
  • proxy_pass的灵活性:如果不想提前定义upstream(你之前的配置里写了upstream),直接用http://容器名:端口更简单,适合动态分支场景;如果是固定服务(比如Jenkins),可以提前定义upstream,但上面的写法已经足够用。
  • 请求头必须设置:尤其是Host头,带Nginx层的前端容器会根据Host头匹配server_name,如果没传对,前端路由会直接404。
步骤3:启动容器并接入网络

把所有容器都加入咱们创建的proxy-net网络:

  1. 启动前端分支容器(比如分支名为dev):
docker run -d --name frontend-dev --network proxy-net your-frontend-image:dev
  1. 启动Jenkins容器:
docker run -d --name some-jenkins --network proxy-net jenkins/jenkins:lts
  1. 启动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配置已经加上。
未来扩展方案

新增容器时,分两种情况:

  1. 动态分支前端:直接启动容器名符合frontend-[分支名]的容器,自动匹配[分支名].a.xyz.com,无需修改Nginx配置。
  2. 固定子域名服务:比如新增abc.xyz.com对应某个服务,只需要在Nginx里新增一个server块,把server_name设为abc.xyz.comproxy_pass指向对应容器的容器名:端口即可。

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

火山引擎 最新活动