直接让两个程序监听同一个端口是不可能的,这会引发冲突,以下是几种主流的部署方案,你可以根据实际需求选择。
这是最通用和专业的解决方案,你让一个反向代理服务(如 Nginx, Apache HTTPD, Caddy)独占服务器的 80/443 端口,反向代理根据不同的域名(或路径等其他规则)将外来请求转发给内部运行在不同端口的各个应用。
工作原理:
1、 用户访问app1.yourdomain.com
,DNS 解析到你的服务器 IP。
2、 服务器的 80/443 端口由 Nginx 监听,它收到请求。
3、 Nginx 查看请求的Host
头(即域名),发现是app1.yourdomain.com
。
4、 Nginx 根据预设规则,将请求转发给本地(127.0.0.1
或localhost
)的 3000 端口(这是你的第一个应用)。
5、 第一个应用处理请求并返回结果给 Nginx,Nginx 再返回给用户。
6、 同理,访问app2.yourdomain.com
的请求会被转发给本地 8000 端口的第二个应用。
优势:
共享端口多个应用共享 80/443 端口。
域名分离可以使用不同域名(或子域名)清晰地区分服务。
附加功能反向代理还能提供 SSL 终止(HTTPS)、负载均衡、缓存、静态文件服务等强大功能。
操作步骤(以 Nginx 为例):
1、安装 Nginx
# Ubuntu/Debian sudo apt update && sudo apt install nginx # CentOS/RHEL sudo yum install nginx sudo systemctl start nginx
2、部署你的应用
假设你有两个 Node.js 应用:
* App1 运行在http://localhost:3000
* App2 运行在http://localhost:8000
3、配置 Nginx 反向代理
在/etc/nginx/conf.d/
目录下为每个应用创建独立的配置文件。
创建app1.conf
server { listen 80; server_name app1.yourdomain.com; # 你的域名1,记得解析DNS location / { proxy_pass http://localhost:3000; # 转发给本地的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.conf
server { listen 80; server_name app2.yourdomain.com; # 你的域名2,记得解析DNS location / { proxy_pass http://localhost:8000; # 转发给本地的App2 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; ... # 其他头部设置同上 } }
4、测试并重载 Nginx 配置
sudo nginx -t # 检查配置文件语法是否正确 sudo systemctl reload nginx # 重载配置,无需重启服务
通过浏览器访问http://app1.yourdomain.com
和http://app2.yourdomain.com
,虽然它们都指向服务器的 80 端口,但 Nginx 会将它们正确路由到不同的内部应用。
如果你的服务器有多个公网 IP 地址,你可以让每个应用绑定一个独立的 IP 并监听 80 端口。
工作原理:
应用A 绑定到IP_1:80
应用B 绑定到IP_2:80
优势:
配置简单直观,无需反向代理。
劣势:
成本高需要多个公网 IP,这在云服务上通常是额外收费的。
管理复杂IP 地址不如域名好记和灵活。
不常用除非有特殊网络要求,否则一般不会采用此方案。
Docker 本身并不解决端口冲突问题,但它提供了更优雅的隔离和管理方式。Docker 会与方案一(反向代理)结合使用。
每个应用运行在独立的 Docker 容器中,每个容器内部都可以使用相同的端口(例如每个容器内的应用都监听 80 端口)。
在启动容器时,通过-p
参数将容器内部的端口映射到宿主机的不同端口上。
# 将容器1的80端口映射到宿主机的3000端口 docker run -d -p 3000:80 your-app1-image # 将容器2的80端口映射到宿主机的8000端口 docker run -d -p 8000:80 your-app2-image
宿主机上就有了两个应用一个在 3000 端口,一个在 8000 端口。
依然需要配置一个 Nginx 反向代理(方案一),将域名请求转发到宿主机的3000
和8000
端口。
优势:
应用与环境隔离,依赖关系清晰。
部署、扩展、迁移非常方便。
Nginx 也可以根据 URL 路径来转发,但通常不推荐用于现代 Web 应用(尤其是单页面应用 SPA 或 API)。
示例配置:
server { listen 80; server_name yourdomain.com; location /app1/ { proxy_pass http://localhost:3000/; # 注意末尾的斜线 } location /app2/ { proxy_pass http://localhost:8000/; } }
访问yourdomain.com/app1/
会转到 App1。
访问yourdomain.com/app2/
会转到 App2。
劣势:
应用需要知道它被部署在某个子路径下,可能需要调整代码(如设置 Webpack 的publicPath
,或 React Router 的basename
),容易出错。
在处理静态资源、API 路由时非常麻烦。
方案 | 核心原理 | 适用场景 | 推荐度 |
反向代理 | 用 Nginx/Apache 监听端口,按域名转发到不同内部端口 | 绝大多数场景,特别是 Web 服务 | ⭐⭐⭐⭐⭐(极力推荐) |
多 IP | 为每个应用分配独立的 IP 地址 | 特殊网络需求,且拥有多个公网 IP | ⭐⭐ |
容器化 | Docker 隔离 + 端口映射,常与反向代理结合 | 需要环境隔离、快速部署的复杂应用 | ⭐⭐⭐⭐ |
路径区分 | 用 Nginx 按 URL 路径转发 | 简单的、临时的服务演示 | ⭐⭐ |
最终建议:
直接采用方案一(Nginx 反向代理),它是最标准、最灵活、最易于维护的方案,几乎适用于所有情况,记得为你的服务购买并配置好域名(或子域名)。
文章摘自:https://idc.huochengrm.cn/fwq/14998.html
评论