# 容器化部署
**本文档引用的文件**
- [docker-compose.yml](file://docker-nginx/docker-compose.yml)
- [bookapi.conf](file://docker-nginx/bookapi.conf)
- [README.md](file://docker-nginx/README.md)
- [DEPLOY.md](file://docs/DEPLOY.md)
- [DEPLOY_PROD.md](file://DEPLOY_PROD.md)
- [server/src/app.ts](file://server/src/app.ts)
- [server/src/config/index.ts](file://server/src/config/index.ts)
- [server/src/services/redis.service.ts](file://server/src/services/redis.service.ts)
- [server/src/services/storage.service.ts](file://server/src/services/storage.service.ts)
- [server/package.json](file://server/package.json)
- [my-uniapp-vue3/package.json](file://my-uniapp-vue3/package.json)
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件面向AI有声书生成平台的容器化部署,聚焦于基于Docker Compose的Nginx反向代理与后端服务编排。内容涵盖:
- Docker Compose配置结构与服务定义
- Nginx反向代理的端口映射、卷挂载与请求转发策略
- 容器间网络通信与数据持久化方案
- 开发与生产环境的配置差异(环境变量、配置文件挂载、日志输出)
- 容器生命周期管理(启动/停止/重启)与健康检查、自动重启机制
## 项目结构
围绕容器化部署的关键文件与目录如下:
- docker-nginx:包含Nginx反向代理的Compose与配置
- server:后端Node.js应用(Koa)
- my-uniapp-vue3:前端UniApp构建产物(H5)
- docs/DEPLOY.md:传统部署与PM2管理说明(参考)
- DEPLOY_PROD.md:生产环境部署与宝塔Nginx配置说明(参考)
```mermaid
graph TB
subgraph "宿主机"
Host["宿主机网络
端口映射: 80->80"]
end
subgraph "容器编排"
Nginx["Nginx容器
nginx-bookapi"]
Backend["后端容器
server"]
end
subgraph "存储"
Uploads["上传目录
/data/ai/audio/server/uploads"]
Videos["视频目录
/data/ai/audio/server/public/videos"]
EnvFile[".env 环境变量
/data/ai/audio/server/.env"]
end
Host --> |"80/tcp"| Nginx
Nginx --> |"http://host.docker.internal:3000"| Backend
Backend --> |"MySQL:3306"| Host
Backend --> |"Redis:6379"| Host
Backend -. 卷挂载 .-> Uploads
Backend -. 卷挂载 .-> Videos
Backend -. 卷挂载 .-> EnvFile
```
图表来源
- [docker-compose.yml:1-12](file://docker-nginx/docker-compose.yml#L1-L12)
- [bookapi.conf:1-15](file://docker-nginx/bookapi.conf#L1-L15)
- [DEPLOY_PROD.md:266-294](file://DEPLOY_PROD.md#L266-L294)
章节来源
- [docker-compose.yml:1-12](file://docker-nginx/docker-compose.yml#L1-L12)
- [bookapi.conf:1-15](file://docker-nginx/bookapi.conf#L1-L15)
- [DEPLOY.md:1-251](file://docs/DEPLOY.md#L1-L251)
- [DEPLOY_PROD.md:1-393](file://DEPLOY_PROD.md#L1-L393)
## 核心组件
- Nginx反向代理服务
- 使用官方Nginx镜像,容器名为nginx-bookapi
- 将宿主80端口映射至容器80端口
- 挂载bookapi.conf作为只读配置文件
- 通过extra_hosts允许容器访问宿主机host.docker.internal
- 重启策略unless-stopped,实现异常退出后的自动重启
- 后端服务(server)
- 基于Node.js/Koa,监听配置中的端口(默认3000)
- 提供/api/*路由与/health健康检查接口
- 通过环境变量控制端口、TTS模型、存储类型、Redis等
- 依赖MySQL与Redis,支持阿里云OSS或本地存储
- 前端(my-uniapp-vue3)
- 构建产物位于dist/,可由Nginx直接提供静态文件服务
- 生产环境Nginx配置中指向/data/ai/audio/frontend/build/h5
章节来源
- [docker-compose.yml:1-12](file://docker-nginx/docker-compose.yml#L1-L12)
- [bookapi.conf:1-15](file://docker-nginx/bookapi.conf#L1-L15)
- [server/src/app.ts:92-94](file://server/src/app.ts#L92-L94)
- [server/src/config/index.ts:69-117](file://server/src/config/index.ts#L69-L117)
- [server/package.json:1-60](file://server/package.json#L1-L60)
- [my-uniapp-vue3/package.json:1-65](file://my-uniapp-vue3/package.json#L1-L65)
## 架构总览
容器化部署采用“Nginx反向代理 + 后端服务”的双容器模式。Nginx负责域名解析与HTTP请求转发,后端处理业务逻辑与数据访问。
```mermaid
sequenceDiagram
participant Client as "客户端浏览器"
participant Nginx as "Nginx容器"
participant Backend as "后端容器"
Client->>Nginx : "HTTP 请求 (bookapi.rrbrr.com)"
Nginx->>Nginx : "解析bookapi.conf
设置X-Forwarded-*头"
Nginx->>Backend : "转发到 http : //host.docker.internal : 3000"
Backend->>Backend : "路由匹配 /api/*"
Backend-->>Nginx : "响应 (JSON/静态资源)"
Nginx-->>Client : "返回响应"
```
图表来源
- [bookapi.conf:5-13](file://docker-nginx/bookapi.conf#L5-L13)
- [server/src/app.ts:92-130](file://server/src/app.ts#L92-L130)
## 详细组件分析
### Nginx反向代理服务
- 服务名称与镜像
- 服务名:nginx
- 镜像:nginx:latest
- 容器名:nginx-bookapi
- 端口映射
- "80:80":将宿主机80端口映射到容器80端口
- 卷挂载
- ./bookapi.conf:/etc/nginx/conf.d/bookapi.conf:ro:挂载只读配置文件
- 网络与主机访问
- extra_hosts配置允许容器解析host.docker.internal
- 重启策略
- unless-stopped:容器非正常退出时自动重启
```mermaid
flowchart TD
Start(["启动 docker-compose"]) --> Pull["拉取nginx镜像"]
Pull --> Create["创建nginx-bookapi容器"]
Create --> Mount["挂载bookapi.conf
只读"]
Mount --> Expose["映射端口80:80"]
Expose --> ExtraHosts["配置host.docker.internal"]
ExtraHosts --> RestartPolicy["设置重启策略: unless-stopped"]
RestartPolicy --> Ready(["Nginx就绪"])
```
图表来源
- [docker-compose.yml:1-12](file://docker-nginx/docker-compose.yml#L1-L12)
章节来源
- [docker-compose.yml:1-12](file://docker-nginx/docker-compose.yml#L1-L12)
- [bookapi.conf:1-15](file://docker-nginx/bookapi.conf#L1-L15)
- [README.md:1-41](file://docker-nginx/README.md#L1-L41)
### 后端服务(server)
- 应用入口与路由
- 健康检查:GET /health
- 路由注册:/api/*各类模块路由
- 环境变量与配置
- 端口:优先SERVER_PORT,其次PORT,默认3000
- JWT密钥与过期时间
- 阿里云百炼TTS相关配置
- 存储类型:oss或local
- Redis连接参数
- 依赖服务
- MySQL:Prisma连接
- Redis:缓存与队列
- OSS:对象存储(可选)
```mermaid
classDiagram
class Config {
+number port
+string nodeEnv
+object jwt
+object dashscope
+object models
+object upload
}
class RedisService {
+isAvailable() boolean
+get(key) Promise~string|null~
+set(key,value,ttl) Promise~boolean~
+getJSON(key) Promise~any~
+setJSON(key,value,ttl) Promise~boolean~
+del(key) Promise~boolean~
+delPattern(pattern) Promise~boolean~
+hset(key,field,value) Promise~boolean~
+hget(key,field) Promise~string|null~
+hgetall(key) Promise~object|null~
}
class StorageService {
+setStorageType(type)
+getStorageType() StorageType
+uploadAudio(localPath,audioId) Promise~string~
+uploadVideo(localPath,videoId) Promise~string~
+uploadCover(localPath,bookId) Promise~string~
+uploadFile(localPath,category,id) Promise~string~
+uploadBuffer(buffer,objectKey,content) Promise~string~
+deleteFile(url) Promise~void~
+deleteDirectory(prefix,id) Promise~void~
+downloadFile(url) Promise~Buffer~
+getSignedUrl(url,expires) Promise~string~
}
Config --> RedisService : "读取Redis配置"
Config --> StorageService : "读取存储类型"
```
图表来源
- [server/src/config/index.ts:69-117](file://server/src/config/index.ts#L69-L117)
- [server/src/services/redis.service.ts:1-200](file://server/src/services/redis.service.ts#L1-L200)
- [server/src/services/storage.service.ts:1-200](file://server/src/services/storage.service.ts#L1-L200)
章节来源
- [server/src/app.ts:92-130](file://server/src/app.ts#L92-L130)
- [server/src/config/index.ts:69-117](file://server/src/config/index.ts#L69-L117)
- [server/src/services/redis.service.ts:1-200](file://server/src/services/redis.service.ts#L1-L200)
- [server/src/services/storage.service.ts:1-200](file://server/src/services/storage.service.ts#L1-L200)
### 容器间网络通信机制
- 默认网络
- Docker Compose默认创建一个桥接网络,容器可通过服务名相互访问
- 宿主机访问
- Nginx容器通过extra_hosts解析host.docker.internal
- 在容器内使用http://host.docker.internal:3000访问宿主机上的后端服务
- 端口暴露
- 宿主机80端口映射至Nginx容器80端口
- 后端服务监听配置端口(默认3000),需确保未被占用
章节来源
- [docker-compose.yml:9-11](file://docker-nginx/docker-compose.yml#L9-L11)
- [bookapi.conf:7-7](file://docker-nginx/bookapi.conf#L7-L7)
### 数据持久化方案
- 上传与视频文件
- 建议将后端uploads与public/videos目录以卷挂载方式持久化
- 生产环境示例路径:/data/ai/audio/server/uploads、/data/ai/audio/server/public/videos
- 环境变量
- 建议将.env文件以卷挂载方式注入容器,便于动态调整配置
- 数据库
- MySQL与Redis建议独立容器或外部服务,通过环境变量连接
章节来源
- [DEPLOY_PROD.md:308-317](file://DEPLOY_PROD.md#L308-L317)
- [server/src/config/index.ts:113-117](file://server/src/config/index.ts#L113-L117)
### 开发环境与生产环境差异
- 端口与域名
- 开发:Nginx监听80,代理到宿主机host.docker.internal:3000
- 生产:宝塔Nginx监听80/443,反向代理到127.0.0.1:3100
- 环境变量
- 生产示例包含:NODE_ENV、SERVER_PORT、JWT_SECRET、DASHSCOPE_*、DATABASE_URL、STORAGE_TYPE、REDIS_*、OSS_*、MINIMAX_API_KEY
- 配置文件挂载
- 开发:Nginx配置文件通过卷挂载
- 生产:宝塔面板管理Nginx配置,路径位于/www/server/panel/vhost/nginx/
- 日志输出
- 后端使用Winston记录日志;生产环境建议结合宝塔日志或容器日志收集
- Nginx访问/错误日志:/var/log/nginx/access.log、/var/log/nginx/error.log
章节来源
- [README.md:1-41](file://docker-nginx/README.md#L1-L41)
- [DEPLOY.md:140-197](file://docs/DEPLOY.md#L140-L197)
- [DEPLOY_PROD.md:105-144](file://DEPLOY_PROD.md#L105-L144)
- [DEPLOY_PROD.md:146-245](file://DEPLOY_PROD.md#L146-L245)
## 依赖关系分析
- 后端服务依赖
- 数据库:Prisma连接MySQL
- 缓存:ioredis连接Redis
- 存储:ossService或本地FS
- Nginx依赖
- 反向代理到后端容器的host.docker.internal:3000
- 前端依赖
- 构建产物H5目录由Nginx提供静态文件服务
```mermaid
graph LR
Nginx["Nginx容器"] --> Backend["后端容器"]
Backend --> MySQL["MySQL服务"]
Backend --> Redis["Redis服务"]
Backend --> OSS["阿里云OSS"]
Frontend["前端H5"] --> Nginx
```
图表来源
- [server/src/app.ts:138-151](file://server/src/app.ts#L138-L151)
- [server/src/services/redis.service.ts:7-38](file://server/src/services/redis.service.ts#L7-L38)
- [server/src/services/storage.service.ts:43-63](file://server/src/services/storage.service.ts#L43-L63)
- [DEPLOY_PROD.md:266-294](file://DEPLOY_PROD.md#L266-L294)
章节来源
- [server/src/app.ts:138-151](file://server/src/app.ts#L138-L151)
- [server/src/services/redis.service.ts:1-200](file://server/src/services/redis.service.ts#L1-L200)
- [server/src/services/storage.service.ts:1-200](file://server/src/services/storage.service.ts#L1-L200)
- [DEPLOY_PROD.md:266-294](file://DEPLOY_PROD.md#L266-L294)
## 性能考虑
- Nginx静态资源缓存与压缩
- 生产Nginx配置中对JS/CSS/图片设置了较长缓存与immutable属性
- 后端性能监控
- 后端内置性能监控中间件与指标接口(/api/metrics)
- 存储与缓存
- Redis缓存提升热点数据访问性能
- OSS适合大规模静态资源分发
- 并发与队列
- 后端使用队列处理长耗时任务(书籍生成等)
章节来源
- [server/src/app.ts:23-24](file://server/src/app.ts#L23-L24)
- [server/src/app.ts:97-97](file://server/src/app.ts#L97-L97)
- [server/src/services/redis.service.ts:1-200](file://server/src/services/redis.service.ts#L1-L200)
- [DEPLOY_PROD.md:223-237](file://DEPLOY_PROD.md#L223-L237)
## 故障排查指南
- Nginx 502/504
- 检查后端服务是否启动且监听指定端口
- 核对Nginx配置与反代地址
- 容器无法访问宿主机
- 确认extra_hosts配置与host.docker.internal解析
- 若无法解析,改用宿主机局域网IP直连
- 后端服务无法启动
- 查看PM2日志或容器日志
- 检查环境变量与数据库连接
- 数据库连接失败
- 检查MySQL容器状态与密码
- 使用Prisma迁移命令进行数据库同步
章节来源
- [README.md:30-41](file://docker-nginx/README.md#L30-L41)
- [DEPLOY.md:200-214](file://docs/DEPLOY.md#L200-L214)
- [DEPLOY_PROD.md:348-375](file://DEPLOY_PROD.md#L348-L375)
## 结论
本容器化方案以Nginx作为统一入口,配合后端服务实现高可用与易维护的部署架构。通过合理的端口映射、卷挂载与环境变量管理,可在开发与生产环境中快速切换。建议在生产中结合宝塔面板或Kubernetes进行更精细的资源调度与监控。
## 附录
### 容器启动/停止/重启标准流程
- 启动
- 开发:进入docker-nginx目录,执行docker-compose up -d
- 验证:curl http://bookapi.rrbrr.com/api/health
- 停止
- docker-compose down
- 重启
- docker-compose restart
- 重载Nginx配置(开发)
- docker-compose exec nginx nginx -s reload
章节来源
- [README.md:5-28](file://docker-nginx/README.md#L5-L28)
### 健康检查与自动重启
- 健康检查
- 后端提供/health接口,可用于外部探针或容器编排健康检查
- 自动重启
- Nginx容器设置restart: unless-stopped
- 生产环境可结合PM2实现后端进程自动重启
章节来源
- [server/src/app.ts:92-94](file://server/src/app.ts#L92-L94)
- [docker-compose.yml:11-11](file://docker-nginx/docker-compose.yml#L11-L11)
- [DEPLOY.md:161-185](file://docs/DEPLOY.md#L161-L185)