Files
2026-06-30 14:46:52 +08:00

349 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 部署与运维
<cite>
**本文引用的文件**
- [docker-compose.yml](file://docker-compose.yml)
- [DEPLOY.md](file://DEPLOY.md)
- [backend/Dockerfile](file://backend/Dockerfile)
- [frontend/Dockerfile](file://frontend/Dockerfile)
- [backend/src/config/env.js](file://backend/src/config/env.js)
- [backend/src/config/loadEnv.js](file://backend/src/config/loadEnv.js)
- [backend/src/config/database.js](file://backend/src/config/database.js)
- [backend/src/config/redis.js](file://backend/src/config/redis.js)
- [backend/src/config/logger.js](file://backend/src/config/logger.js)
- [scripts/upload.sh](file://scripts/upload.sh)
- [backend/package.json](file://backend/package.json)
- [frontend/package.json](file://frontend/package.json)
- [backend/start.sh](file://backend/start.sh)
- [backend/restart.sh](file://backend/restart.sh)
- [backend/stop.sh](file://backend/stop.sh)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件面向部署与运维工程师,系统性说明项目的容器化部署、环境配置、生产部署流程、容器编排、服务依赖与网络设置、部署脚本使用、自动化流程、环境变量与数据库/缓存配置、监控与日志、性能调优、故障排除、备份恢复与灾难恢复、CI/CD 与版本发布/回滚策略,以及安全配置与访问控制。
## 项目结构
- 前端采用 Nginx 静态托管,后端为 Node.js API,二者通过 Docker Compose 在同一自定义桥接网络中通信。
- 前端不构建镜像,直接挂载服务器上的构建产物与 Nginx 配置;后端以独立镜像运行。
- 日志轮转策略在 Compose 层统一配置,便于生产环境管理。
- OTA 升级包本地存储通过宿主机卷挂载到后端容器,确保升级资源可用性。
```mermaid
graph TB
subgraph "宿主机"
V1["/data/projects/source<br/>OTA 存储卷"]
FDist["/data/project/dashboard/frontend/dist<br/>前端静态资源"]
NConf["/data/project/dashboard/frontend/nginx.conf<br/>Nginx 配置"]
end
subgraph "Docker 网络 audio-network"
FE["容器 dashboard-frontend<br/>Nginx:80"]
BE["容器 dashboard-backend<br/>Node.js:8000"]
end
V1 --> BE
FDist --> FE
NConf --> FE
FE --> |"反向代理 /api → http://backend:8000"| BE
```
图表来源
- [docker-compose.yml:7-46](file://docker-compose.yml#L7-L46)
章节来源
- [docker-compose.yml:1-46](file://docker-compose.yml#L1-L46)
- [DEPLOY.md:1-120](file://DEPLOY.md#L1-L120)
## 核心组件
- 后端服务(Node.js
- 基于 Node.js 22 Alpine 镜像,使用 pnpm 生产依赖安装,工作目录包含日志目录,暴露 8000 端口。
- 通过环境变量驱动数据库、Redis、搜索、S3、OTA 等配置。
- 前端服务(Nginx
- 使用 Nginx Alpine 镜像,挂载静态资源与 Nginx 配置,不构建镜像,减少部署复杂度。
- 容器编排与网络
- Compose 定义自定义桥接网络,前后端在同一网络内通信;前端通过 Nginx 将 /api 代理到后端容器的 8000 端口。
- 部署脚本
- 提供一键上传前端、后端、Compose 的 rsync 脚本,支持虚拟执行与多目标组合。
章节来源
- [backend/Dockerfile:1-20](file://backend/Dockerfile#L1-L20)
- [frontend/Dockerfile:1-32](file://frontend/Dockerfile#L1-L32)
- [docker-compose.yml:7-46](file://docker-compose.yml#L7-L46)
- [scripts/upload.sh:1-191](file://scripts/upload.sh#L1-L191)
## 架构总览
- 端口映射
- 前端 Nginx 暴露 80,映射到宿主机 8082。
- 后端 Node.js 暴露 8000,映射到宿主机 8083。
- 服务依赖
- 前端依赖后端 APICompose 通过 depends_on 实现启动顺序。
- 网络
- 两容器加入同一自定义桥接网络,实现容器间通过服务名访问。
- 日志
- 每个服务启用 JSON 文件日志轮转,单文件最大 10MB,最多 5 个文件。
```mermaid
sequenceDiagram
participant U as "用户浏览器"
participant FE as "dashboard-frontend(Nginx)"
participant BE as "dashboard-backend(Node.js)"
U->>FE : "访问 http : //<host> : 8082/"
FE->>FE : "解析路由与静态资源"
U->>FE : "请求 /api/*"
FE->>BE : "反向代理到 http : //backend : 8000"
BE-->>FE : "返回 API 响应"
FE-->>U : "返回 HTML/JS/CSS 与 API 数据"
```
图表来源
- [docker-compose.yml:28-41](file://docker-compose.yml#L28-L41)
- [DEPLOY.md:114-118](file://DEPLOY.md#L114-L118)
章节来源
- [DEPLOY.md:5-118](file://DEPLOY.md#L5-L118)
- [docker-compose.yml:1-46](file://docker-compose.yml#L1-L46)
## 详细组件分析
### 后端容器与应用配置
- 环境变量加载
- 容器内通过根目录 .env 注入;本地开发与 Docker 部署共享同一 .env 加载逻辑,但 Docker 下容器内无 .env 文件,由 Compose 注入。
- 环境类型
- 通过 APP_ENV 判断开发/生产环境,影响日志输出等行为。
- 数据库连接
- 使用 Sequelize 连接 MySQL,支持主机、端口、用户名、密码、字符集、日志开关等配置项。
- Redis 缓存
- 提供 EQ 缓存客户端工厂方法,支持主机、端口、密码、数据库编号、超时与重试配置,并记录错误日志。
- 日志
- 使用 Winston 输出到控制台与文件,日志目录位于应用内部 logs 子目录。
```mermaid
flowchart TD
Start(["启动后端"]) --> LoadEnv["加载根目录 .envCompose 注入"]
LoadEnv --> EnvCheck{"APP_ENV 是否为 production"}
EnvCheck --> |是| Prod["生产模式:关闭 ORM 日志"]
EnvCheck --> |否| Dev["开发模式:开启 ORM 日志"]
Prod --> DB["初始化数据库连接Sequelize"]
Dev --> DB
DB --> RedisInit["初始化 Redis 客户端"]
RedisInit --> Logger["初始化日志记录器"]
Logger --> Ready(["服务就绪"])
```
图表来源
- [backend/src/config/loadEnv.js:1-15](file://backend/src/config/loadEnv.js#L1-L15)
- [backend/src/config/env.js:1-13](file://backend/src/config/env.js#L1-L13)
- [backend/src/config/database.js:1-24](file://backend/src/config/database.js#L1-L24)
- [backend/src/config/redis.js:1-32](file://backend/src/config/redis.js#L1-L32)
- [backend/src/config/logger.js:1-29](file://backend/src/config/logger.js#L1-L29)
章节来源
- [backend/src/config/loadEnv.js:1-15](file://backend/src/config/loadEnv.js#L1-L15)
- [backend/src/config/env.js:1-13](file://backend/src/config/env.js#L1-L13)
- [backend/src/config/database.js:1-24](file://backend/src/config/database.js#L1-L24)
- [backend/src/config/redis.js:1-32](file://backend/src/config/redis.js#L1-L32)
- [backend/src/config/logger.js:1-29](file://backend/src/config/logger.js#L1-L29)
### 前端容器与 Nginx 配置
- 镜像与构建
- 使用 Nginx Alpine 镜像,挂载静态资源与 Nginx 配置文件,不构建前端镜像。
- 代理规则
- 前端通过 Nginx 将 /api 代理到后端容器的 8000 端口,确保 SPA 与 API 请求分离。
- 卷挂载
- 前端 dist 与 nginx.conf 通过宿主机卷挂载,便于快速更新与热替换。
章节来源
- [frontend/Dockerfile:1-32](file://frontend/Dockerfile#L1-L32)
- [docker-compose.yml:28-41](file://docker-compose.yml#L28-L41)
### 容器编排与网络
- 自定义桥接网络
- 两容器加入同一网络,实现通过服务名访问后端 API。
- 端口映射
- 前端 80:8082,后端 8000:8083,避免端口冲突。
- 日志轮转
- 每个服务启用 JSON 文件日志轮转,单文件 10MB,最多 5 份。
章节来源
- [docker-compose.yml:43-46](file://docker-compose.yml#L43-L46)
- [docker-compose.yml:1-5](file://docker-compose.yml#L1-L5)
### 部署脚本与自动化
- 功能特性
- 支持同步前端、后端、Compose 三类目标,也支持指定路径与虚拟执行。
- 默认目标包含前端 dist、后端 src 与依赖锁文件、Compose 文件。
- SSH 密钥与远程路径可配置,便于跨环境复用。
- 使用场景
- 本地构建前端后,一键上传前端与 Compose 并在服务器执行 docker compose up -d。
- 后端代码变更后,上传后端文件并在服务器重建后端镜像并启动。
```mermaid
sequenceDiagram
participant Dev as "开发者"
participant Script as "upload.sh"
participant Server as "服务器"
Dev->>Script : "执行 ./scripts/upload.sh frontend"
Script->>Server : "rsync 前端 dist 到 /data/project/dashboard/frontend/dist"
Dev->>Script : "执行 ./scripts/upload.sh compose"
Script->>Server : "rsync docker-compose.yml"
Dev->>Server : "在服务器执行 docker compose up -d"
Server-->>Dev : "验证服务状态与日志"
```
图表来源
- [scripts/upload.sh:1-191](file://scripts/upload.sh#L1-L191)
- [DEPLOY.md:49-113](file://DEPLOY.md#L49-L113)
章节来源
- [scripts/upload.sh:1-191](file://scripts/upload.sh#L1-L191)
- [DEPLOY.md:49-113](file://DEPLOY.md#L49-L113)
### 本地开发与非容器部署
- 本地开发
- 后端在 8083 端口启动,前端在 3000 端口启动并通过代理转发 /api 到后端。
- 非容器部署
- 通过 start.sh/stop.sh/restart.sh 管理本地进程,便于调试与快速迭代。
章节来源
- [DEPLOY.md:259-269](file://DEPLOY.md#L259-L269)
- [backend/start.sh:1-5](file://backend/start.sh#L1-L5)
- [backend/stop.sh:1-14](file://backend/stop.sh#L1-L14)
- [backend/restart.sh:1-43](file://backend/restart.sh#L1-L43)
## 依赖分析
- 后端依赖
- Web 框架、ORM、MySQL 驱动、JWT、S3 SDK、Redis 客户端、日志、校验等。
- 前端依赖
- Vue 3、Element Plus、路由、HTTP 客户端等。
- 版本锁定
- 后端与前端均使用 pnpm 并固定版本,保证构建一致性。
```mermaid
graph LR
BE["后端 Node.js"] --> PkgBE["package.json 依赖"]
FE["前端 Vue 应用"] --> PkgFE["package.json 依赖"]
PkgBE --> Express["express"]
PkgBE --> Sequelize["sequelize + mysql2"]
PkgBE --> JWT["jsonwebtoken"]
PkgBE --> S3["@aws-sdk/client-s3"]
PkgBE --> Redis["ioredis"]
PkgBE --> Winston["winston"]
PkgBE --> Dotenv["dotenv"]
PkgFE --> Vue["vue"]
PkgFE --> EP["element-plus"]
PkgFE --> Axios["axios"]
PkgFE --> Router["vue-router"]
```
图表来源
- [backend/package.json:11-27](file://backend/package.json#L11-L27)
- [frontend/package.json:10-22](file://frontend/package.json#L10-L22)
章节来源
- [backend/package.json:1-29](file://backend/package.json#L1-L29)
- [frontend/package.json:1-24](file://frontend/package.json#L1-L24)
## 性能考虑
- 日志轮转
- Compose 层启用日志轮转,避免磁盘膨胀;建议结合系统日志聚合与保留策略。
- 静态资源优化
- 前端构建产物通过 Nginx 提供,建议配合缓存头与压缩策略提升首屏性能。
- 数据库与缓存
- 生产环境建议使用专用数据库与 Redis 实例,合理设置连接池与超时参数。
- 容器资源
- 建议在生产环境中为容器设置 CPU/内存限制与健康检查,增强稳定性。
- CDN 与反代
- 对静态资源与 API 可引入反向代理与 CDN,降低后端压力。
## 故障排除指南
- 前端页面空白
- 检查 dist 是否上传成功、Nginx 代理是否指向后端 8000 端口、浏览器控制台是否存在 404。
- API 请求失败
- 确认后端容器处于 running 状态、查看后端日志定位数据库/Redis/Meilisearch 连接问题。
- 后端构建失败(pnpm/Node 版本)
- 确保上传了 package.json 与 pnpm-lock.yaml,后端镜像基于 node:22-alpine。
- .env 修改不生效
- 通过重新创建容器使新环境变量生效。
- 停止/重启服务
- 使用 docker compose down 或在服务器执行 restart.sh/stop.sh/stop.sh 管理本地进程。
章节来源
- [DEPLOY.md:226-256](file://DEPLOY.md#L226-L256)
- [backend/restart.sh:1-43](file://backend/restart.sh#L1-L43)
- [backend/stop.sh:1-14](file://backend/stop.sh#L1-L14)
## 结论
本项目采用轻量化的容器化方案:前端 Nginx 静态托管、后端 Node.js API,通过 Compose 统一编排与网络隔离,辅以集中式 .env 管理与 rsync 自动化脚本,形成可重复、可审计的生产部署流程。建议在生产中进一步完善资源限制、健康检查、日志聚合与监控告警体系,以满足高可用与可观测性要求。
## 附录
### 环境变量与配置清单
- 数据库
- DATABASE_HOST、DATABASE_PORT、DATABASE_NAME、DATABASE_USER、DATABASE_PASSWORD
- 应用
- APP_NAME、APP_ENV
- 认证
- JWT_SECRET、DASHBOARD_ADMIN_USERNAME、DASHBOARD_ADMIN_PASSWORD
- 搜索
- MEILISEARCH_URL、MEILISEARCH_API_KEY、MEILISEARCH_INDEX
- S3
- AWS_REGION、AWS_S3_OTA_BUCKET、AWS_S3_MEASUREMENT_BUCKET
- OTA
- OTA_X8_PUBLIC_BASE、OTA_X9_URL_BASE、OTA_UPLOAD_DIR
- Redis EQ
- REDIS_HOST、REDIS_PORT、REDIS_PASSWORD、REDIS_EQ_DB
章节来源
- [DEPLOY.md:190-203](file://DEPLOY.md#L190-L203)
### 目录结构(服务器)
- /data/project/dashboard/
- .env、docker-compose.yml、backend/(含 Dockerfile、package.json、pnpm-lock.yaml、src/)、frontend/dist、nginx.conf
- /data/projects/source/OTA 升级包存储)
章节来源
- [DEPLOY.md:206-223](file://DEPLOY.md#L206-L223)
### 监控指标与日志管理
- 指标
- 建议采集容器 CPU/内存/IO、API 响应时间与错误率、数据库连接数、Redis 命中率等。
- 日志
- 后端日志写入容器内 logs 文件,结合 Compose 日志轮转;建议接入集中式日志系统进行检索与告警。
章节来源
- [backend/src/config/logger.js:1-29](file://backend/src/config/logger.js#L1-L29)
- [docker-compose.yml:1-5](file://docker-compose.yml#L1-L5)
### 备份与灾难恢复
- 数据库
- 定期导出 MySQL 数据,保存至安全位置或对象存储。
- 配置与代码
- .env 与源码版本化管理,确保可追溯与快速回滚。
- OTA 存储
- /data/projects/source 作为本地存储,建议异地复制或对象存储归档。
- 灾难恢复
- 准备最小化恢复步骤:拉起 Compose、恢复 .env、恢复数据库快照、恢复静态资源与 Nginx 配置。
### CI/CD 流程、版本发布与回滚
- 流程建议
- 代码合并触发流水线:前端构建、后端构建、上传脚本执行、Compose 启动。
- 发布与回滚
- 以标签/分支为版本依据;回滚时使用相同镜像版本或恢复 .env 快照,必要时回退数据库迁移。
### 安全配置、防火墙与访问控制
- 端口与防火墙
- 仅开放 8082(前端)、8083(后端)与必要的系统端口;限制来源 IP。
- 认证与密钥
- 生产环境务必更换 JWT_SECRET、管理员密码;S3 优先使用 IAM 角色而非明文凭据。
- 网络隔离
- 将数据库与缓存置于隔离网络,仅允许后端容器访问;必要时启用网络策略。