在同一个服务器上部署多个 Web 应用,核心思路就两个:“端口隔离”和“反向XX”。
别被那些复杂的架构图吓到,实际生产环境中,我们主要靠 Nginx(或 Caddy/Traefik) 做流量分发,配合 Docker 或者 Systemd 来管理进程。下面我按从简单到专业、从单机到云原生几个层级,把几种主流方案拆解给你看。
方案一:不同端口直连(适合开发测试或极少应用)
这是最原始但也最直观的方法。假设你有两个应用:
- App A:运行在
8080端口 - App B:运行在
8081端口
用户访问时,必须带上端口号,比如 http://IP:8080 和 http://IP:8081。
优点:配置极简,无需额外软件。
缺点:
- 用户体验差,URL 里带端口不优雅。
- 安全性低,直接暴露了内部服务端口。
- HTTPS 证书管理麻烦,每个端口都要单独搞 SSL。
- 端口多了之后,防火墙规则(iptables/firewalld)难维护。
结论:除非是个人玩玩或者内网调试,否则生产环境坚决不用这个。
方案二:基于域名的虚拟主机 + Nginx 反向XX(最经典、最常用)
这是目前中小型企业和个人开发者使用最多的方案。核心逻辑是:所有 HTTP/HTTPS 请求先到达 Nginx,Nginx 根据域名判断,把流量转发给后不同的后端服务。
架构示意:
用户浏览器
|
| (http://app1.com)
v
Nginx (监听 80/443)
|--> Proxy Pass --> Node.js App A (localhost:3000)
|
| (http://app2.com)
v
Nginx (监听 80/443)
|--> Proxy Pass --> Python/Django App B (localhost:8000)
实施步骤简述:
-
启动你的 Web 应用
确保你的 App A 监听在127.0.0.1:3000,App B 监听在127.0.0.1:8000。注意绑定 localhost,不要绑定 0.0.0.0,防止外部直接绕过 Nginx 访问。 -
安装 Nginx
sudo apt install nginx # Ubuntu/Debian sudo yum install nginx # CentOS -
配置 Nginx
在/etc/nginx/conf.d/下创建配置文件,例如app1.conf:server { listen 80; server_name app1.example.com; location / { proxy_pass http://127.0.0.1:3000; 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,指向127.0.0.1:8000。 -
加载配置并重启
nginx -t # 检查语法 systemctl reload nginx -
搞定 HTTPS(重要)
现在大家都用 HTTPS。推荐使用 Certbot 自动申请 Let’s Encrypt 免费证书:sudo certbot --nginx -d app1.example.com -d app2.example.comCertbot 会自动修改你的 Nginx 配置,添加 SSL 部分,非常省心。
优点:
- 一个 IP、一个端口(443)搞定所有应用。
- 统一 SSL 证书管理。
- Nginx 可以做负载均衡、静态资源缓存、限流等高级功能。
- 对后端语言无限制(Java, Go, Node, Python 都行)。
缺点:
- 需要学习 Nginx 配置语法。
- 如果 Nginx 挂了,所有应用都不可用(单点故障,但可以通过 Keepalived+VIP 解决,不过对于单机部署通常没必要)。
方案三:Docker Compose 容器化部署(现代标准做法)
如果你追求环境一致性、易迁移、易扩展,强烈建议上 Docker。
为什么选 Docker?
- 隔离性:每个应用跑在自己的容器里,互不干扰。
- 依赖管理:Node 的 npm、Python 的 pip、Java 的 jar,都在镜像里打包好,不会出现“在我机器上能跑”的问题。
- 编排简单:一个
docker-compose.yml文件定义所有服务。
示例结构:
version: '3.8'
services:
nginx:
image: nginx:latest
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./certs:/etc/nginx/certs
depends_on:
- app-a
- app-b
restart: always
app-a:
build: ./app-a
expose:
- "3000"
environment:
- NODE_ENV=production
restart: always
app-b:
build: ./app-b
expose:
- "8000"
environment:
- DJANGO_SETTINGS_MODULE=config.settings
restart: always
关键点:
- Nginx 作为入口:只有 Nginx 容器暴露 80/443 端口给宿主机。其他应用只通过 Docker 内部网络通信。
- Proxy 配置:在 Nginx 的 conf 中,
proxy_pass指向的不是127.0.0.1,而是 Docker 内部的 service name,如http://app-a:3000。Docker DNS 会自动解析。 - 数据持久化:通过 Volumes 挂载日志、证书、上传文件等。
优点:
- 部署即插即用,换服务器只需复制代码和 docker-compose.yml。
- 资源隔离好,避免依赖冲突。
- 易于横向扩展(加几个副本即可)。
缺点:
- 有一定学习曲线(Dockerfile, Network, Volume 概念)。
- 对于极简小项目,可能有点“杀鸡用牛刀”。
方案四:云厂商提供的轻量级解决方案(阿里云/腾讯云等)
如果你用的是国内云厂商的 ECS 或轻量应用服务器,他们其实提供了一些简化操作:
-
Web 应用托管(SAE/PaaS):
像阿里云的 SAE(Serverless App Engine)或腾讯云的微服务平台,你只需要上传代码包或镜像,平台自动帮你配好 Nginx、负载均衡、HTTPS。你根本不需要关心“如何在同一台服务器部署”,因为底层可能是多台服务器集群,对你透明。 -
宝塔面板(BT Panel):
如果是个人站长或小团队,不想敲命令,宝塔面板是国内最流行的图形化管理工具。- 一键安装 Nginx。
- 一键添加网站,自动分配域名、SSL。
- 支持 PHP、Node.js、Java 等多种环境的一键部署。
- 后台可以直接看到 CPU、内存、磁盘 IO。
注意:宝塔虽然方便,但要注意安全。默认端口要改,强密码,定期更新面板。另外,部分企业出于合规和安全审计考虑,禁止使用第三方控制面板,需自行评估。
避坑指南 & 最佳实践
-
不要把所有东西都塞进一个进程
比如,不要把前端静态文件、后端 API、数据库驱动全部写在一个 Express 或 Flask 应用里然后混在一起跑。保持关注点分离。 -
日志收集
多个应用共用一台服务器,日志容易混乱。- 每个应用输出 JSON 格式日志。
- 使用 Loki + Grafana 或 ELK 集中收集日志。
- 至少要做到:能通过应用名过滤日志,而不是在一堆文本里找自己的报错。
-
资源限制(Cgroups)
如果某个应用突然内存泄漏,会把整个服务器撑爆,导致其他应用也挂掉。- 如果用 Docker,设置
deploy.resources.limits.memory。 - 如果用 Systemd,设置
MemoryLimit=或MemoryMax=。
- 如果用 Docker,设置
-
安全加固
- 关闭不必要的端口。
- 使用 Fail2ban 防止暴力破解 SSH。
- 定期更新操作系统和 Nginx 版本。
- 敏感信息(数据库密码、API Key)不要写在代码里,用环境变量注入。
-
备份策略
再好的架构,硬盘坏了也没用。- 每天备份数据库。
- 每周备份网站代码和配置文件。
- 异地备份(比如 OSS/S3 存储)。
总结建议
- 新手/个人博客/小站:直接用 宝塔面板,最快最省事。
- 正经项目开发/团队协作:使用 Docker Compose + Nginx,标准化、可移植。
- 高并发/大规模生产环境:放弃单机思维,上 Kubernetes (K8s) 或云厂商的 PaaS 服务,这时候“同一台服务器”已经不是一个合理的约束条件了。
希望这些内容能帮到你。如果有具体的技术栈(比如你是 Java 还是 Node.js),可以进一步细化配置细节。
云技术博客