非容器模式
容器模式
在一个 VPS 上部署前后端时,最科学、最省资源的方案是:利用前端容器自带的 Nginx 兼职做全站反代。
在这种情况下,只需要 一个 Nginx(即前端容器里的那个) 就可以处理所有事情:发送 HTML、解决 SPA 路由、转发 API 请求。
以下是针对“同机部署”的两种模板:
方案一:本地构建模式 (Build 模式)
适用场景:你在 VPS 上拉取了源码,想直接根据源码生成镜像并运行。
📂 目录结构
/opt/sitebox/
├── frontend/ # 前端源码 (含 Dockerfile 和 nginx.conf)
├── backend/ # 后端源码 (含 Dockerfile 和 server.node.js)
└── docker-compose.yml
🚀 docker-compose.yml (Build)
version: '3.8'
services:
# 前端:既是网页服务器,也是 API 网关
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: sitebox-frontend
restart: always
ports:
- "80:80" # 外部通过 80 端口访问整个项目
environment:
- BACKEND_PROTO=http
- BACKEND_ADDR=backend:3000 # 使用内部服务名,流量不走公网,安全且快
- BACKEND_HOST=backend
networks:
- sitebox-net
# 后端:纯 API 服务
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: sitebox-backend
restart: always
expose:
- "3000" # 端口只对容器开放
# ports:
# - "3000:3000" # 端口对公网开放,比如给插件使用
environment:
- PORT=3000
- DB_PATH=/app/data/db/sitebox.db
- DEPLOY_MODE=docker
# 如果要同步到github这下面三个参数是必填项
- GITHUB_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxx
- GITHUB_REPO=xxxxxx/yyyyyyyy
- GITHUB_PATH=backup_json/backup.json
volumes:
- ./data/db:/app/data/db # 持久化数据库
networks:
- sitebox-net
networks:
sitebox-net:
driver: bridge
方案二:远程镜像模式 (Image 模式)
适用场景:已经在本地打包好镜像推送到 Docker Hub,VPS 只需要一行命令直接起飞。
🚀 docker-compose.yml (Image)
version: '3.8'
services:
frontend:
image: your-username/sitebox-frontend:latest
container_name: sitebox-frontend
restart: always
ports:
- "80:80"
environment:
- BACKEND_PROTO=http
- BACKEND_ADDR=backend:3000
- BACKEND_HOST=backend
networks:
- sitebox-net
backend:
image: your-username/sitebox-backend:latest
container_name: sitebox-backend
restart: always
expose:
- "3000" # 端口只对容器开放
# ports:
# - "3000:3000" # 端口对公网开放,比如给插件使用
environment:
- PORT=3000
- DB_PATH=/app/data/db/sitebox.db
- DEPLOY_MODE=docker
# 如果要同步到github这下面三个参数是必填项
- GITHUB_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxx
- GITHUB_REPO=xxxxxx/yyyyyyyy
- GITHUB_PATH=backup_json/backup.json
volumes:
- /opt/sitebox/data/db:/app/data/db
networks:
- sitebox-net
networks:
sitebox-net:
driver: bridge
❓ 关键问题解答
1. 为什么只需要“前端 Nginx”?
因为你的前端镜像 Dockerfile 里已经集成了 Nginx,并且我们写好了 ${BACKEND_ADDR} 模板。
- 用户访问
http://VPS_IP/-> 命中前端 Nginx -> 返回 HTML。 - 网页发起
/api/请求 -> 命中前端 Nginx -> Nginx 根据BACKEND_ADDR=backend:3000转发给同机后端。 - 结论: 不需要额外在宿主机装 Nginx,前端容器里的 Nginx 就把活全干了。
2. 什么时候需要“第二个 Nginx”?
只有当你遇到以下两种情况时,你才需要在 宿主机(Host) 上额外再套一个 Nginx:
- 如果你要配 HTTPS/SSL:虽然容器里也能配,但在宿主机上用
Nginx Proxy Manager或Certbot管理证书更方便。 - 如果你一台 VPS 要跑多个网站:比如
a.com跑 SiteBox,b.com跑博客。这时宿主机 Nginx 负责分流:a.com转发给前端容器,b.com转发给博客容器。
3. 关于 BACKEND_ADDR 的填写
在同一个 docker-compose.yml 下,千万不要填公网 IP。
- 错误写法:
BACKEND_ADDR=1.2.3.4:3000(流量会绕公网一圈,慢且不安全)。 - 正确写法:
BACKEND_ADDR=backend:3000(走 Docker 内部虚拟交换机,极速)。
💡 总结建议
对于你在同一台 VPS 上的部署:
- 镜像:前端一个(含 Nginx),后端一个(Node)。
- Nginx 实例:只运行 前端容器里的那一个。
- 配置:通过
docker-compose的environment让前端 Nginx 准确定位到名为backend的后端服务。
这样VPS 占用内存最小,配置也最清晰,完全发挥了容器化的优势!