非容器模式

前端部署 后端部署

容器模式

在一个 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:

  1. 如果你要配 HTTPS/SSL:虽然容器里也能配,但在宿主机上用 Nginx Proxy ManagerCertbot 管理证书更方便。
  2. 如果你一台 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-composeenvironment 让前端 Nginx 准确定位到名为 backend 的后端服务。

这样VPS 占用内存最小,配置也最清晰,完全发挥了容器化的优势!