如何把不同子域名转发到同一服务器的不同端口

用 Apache 的 VirtualHost + ProxyPass(或 Nginx 的 server 块 + proxy_pass)按域名把请求反向代理到本机不同端口,用户访问 app.example.com 实际由 8080 端口服务。附完整配置与 WebSocket 处理。

最佳实践
应用程序模块协作插画

一句话回答:用反向代理按域名分发:Apache 里为每个子域名建一个 VirtualHost,用 ProxyPass / http://localhost:端口/ 转发;Nginx 里同理用 server 块 + proxy_pass。这样 app.example.com、api.example.com 都走 80/443 进入,实际分别由本机 8080、3000 端口的服务处理,用户完全看不到端口号。

Apache 配置

先启用代理模块:

sudo a2enmod proxy proxy_http
sudo systemctl restart apache2

为每个子域名建 VirtualHost:

<VirtualHost *:80>
    ServerName app.example.com
    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>

<VirtualHost *:80>
    ServerName api.example.com
    ProxyPass / http://127.0.0.1:3000/
    ProxyPassReverse / http://127.0.0.1:3000/
</VirtualHost>

ProxyPassReverse 的作用是改写后端响应里的重定向地址,建议配套配置;它不改写 HTML 内容或所有 Cookie 属性,应用的外部 URL 配置也要正确。

Nginx 等价配置

server {
    listen 80;
    server_name app.example.com;
    location / {
        proxy_pass http://127.0.0.1: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;
    }
}

这些转发头让后端获得入口看到的 Host/IP 信息;应用只应信任来自已知代理的头,不能无条件信任客户端自带的 X-Forwarded-For。容器分离部署时 127.0.0.1 未必指向后端,应换为可达服务地址。

WebSocket 服务要额外处理

如果被代理的服务用 WebSocket(如热更新、实时推送),需要升级头支持:

# Nginx:location 块内加
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

配套事项

  1. DNS:各子域名用 A/AAAA 或合适的 CNAME 解析到代理入口;DNS 不负责端口路由
  2. HTTPS:生产环境给每个子域名配证书(或一张泛域名证书),用 Certbot 可自动签发并改写配置
  3. 后端服务绑定 127.0.0.1:8080/3000 端口只监听本机,外部无法绕过代理直连,更安全

逐一请求各子域名,核对响应来自预期后端;同时查看代理访问日志中的域名与上游地址,防止多个域名误入默认站点。

常见问题(FAQ)

Q:为什么不用 子域名:端口 直接访问,非要反向代理?

A:三个原因:URL 里的端口号对普通用户不友好;很多公司/校园网络封非标准端口,8080 直接访问会被拦;HTTPS 证书和统一入口难以管理。反向代理用标准 80/443 一口进,内部按域名分流,是标准做法。

Q:配置后访问子域名出现 503?

A:503 可能来自代理或后端,不能只凭状态码断定端口拒绝连接;结合错误日志:确认后端服务在跑(ss -tlnp | grep 8080)、后端没崩;Apache 场景还可检查 SELinux 拒绝日志,确认策略原因后由管理员按最小权限调整,勿直接放宽全局策略。

Q:不同子域名必须指向不同端口吗?

A:不一定。如果多个子域名由同一个应用处理(如多租户),可以让多个 server_name 共用同一个 proxy_pass 目标,应用内按 Host 头区分租户。

核查依据

本文依据官方文档核对,示例未在实际业务环境运行;上线前请按部署版本、权限与数据范围验证。


延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台