将部署链路调整为 CI 构建推送镜像、服务器拉取镜像运行,并拆分/复用 Gitea workflow 与公共准备脚本;同时统一 APP_NAME 与端口变量配置,补充 Docker 与 ESLint 相关配置文件以提升可维护性。 Made-with: Cursor
This commit is contained in:
167
docs/deploy-docker-compose.md
Normal file
167
docs/deploy-docker-compose.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# ChatOne Service Docker 部署(Compose)
|
||||
|
||||
本文提供单机 Docker Compose 部署方案,包含 `app`(数据库与 Redis 使用远程实例)。
|
||||
域名、HTTPS、反向代理统一在宿主机 Nginx 处理。
|
||||
|
||||
## 1. 文件位置
|
||||
|
||||
- `deploy/docker/Dockerfile`
|
||||
- `deploy/docker/app.entrypoint.sh`
|
||||
- `deploy/docker/ecosystem.config.cjs`
|
||||
- `deploy/docker/docker-compose.yml`
|
||||
- `deploy/docker/.env.example`
|
||||
|
||||
## 2. 初始化
|
||||
|
||||
```bash
|
||||
cd deploy/docker
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
修改 `.env` 中所有密钥与密码,至少包括:
|
||||
|
||||
- `JWT_ACCESS_SECRET`
|
||||
- `JWT_REFRESH_SECRET`
|
||||
- `QWEN_API_KEY`(如使用)
|
||||
- `DATABASE_URL`
|
||||
- `REDIS_PASSWORD`
|
||||
- `IMAGE_REPO`
|
||||
- `IMAGE_TAG`
|
||||
|
||||
请将 `DATABASE_URL`、`REDIS_HOST`、`REDIS_PASSWORD` 替换为远程实例配置。
|
||||
镜像发布模式说明:
|
||||
|
||||
- CI 负责构建并推送 `${IMAGE_REPO}:${IMAGE_TAG}`
|
||||
- 目标服务器仅执行 `docker compose pull + up`
|
||||
|
||||
端口统一约定:
|
||||
|
||||
- `PORT`:容器内应用监听端口
|
||||
- `HOST_BIND_PORT`:宿主机绑定端口(供宿主机 Nginx 反代)
|
||||
|
||||
## 3. 启动
|
||||
|
||||
在项目根目录执行:
|
||||
|
||||
```bash
|
||||
docker compose -f deploy/docker/docker-compose.yml --env-file deploy/docker/.env up -d --build
|
||||
```
|
||||
|
||||
查看状态:
|
||||
|
||||
```bash
|
||||
docker compose -f deploy/docker/docker-compose.yml ps
|
||||
docker compose -f deploy/docker/docker-compose.yml logs -f app
|
||||
```
|
||||
|
||||
## 4. 验证
|
||||
|
||||
```bash
|
||||
curl -i http://127.0.0.1:${HOST_BIND_PORT}/api/docs
|
||||
```
|
||||
|
||||
SSE 冒烟:
|
||||
|
||||
- `POST /api/client/v1/chat/completions/stream`
|
||||
|
||||
## 5. 发布升级
|
||||
|
||||
拉取新代码后执行:
|
||||
|
||||
```bash
|
||||
docker compose -f deploy/docker/docker-compose.yml --env-file deploy/docker/.env up -d --build app
|
||||
```
|
||||
|
||||
数据库迁移会在 `app` 容器启动时自动执行(`npx prisma migrate deploy`)。
|
||||
应用进程由容器内 `pm2-runtime` 管理。
|
||||
|
||||
## 6. 回滚
|
||||
|
||||
推荐在发布前打镜像标签,例如:
|
||||
|
||||
```bash
|
||||
docker build -f deploy/docker/Dockerfile -t chat-one-service:20260426 .
|
||||
```
|
||||
|
||||
回滚时将 compose 中 `app.image` 改为旧标签,然后:
|
||||
|
||||
```bash
|
||||
docker compose -f deploy/docker/docker-compose.yml --env-file deploy/docker/.env up -d app
|
||||
```
|
||||
|
||||
## 7. 生产建议
|
||||
|
||||
- 不要把 `.env` 提交到仓库。
|
||||
- `app` 仅监听本机 `127.0.0.1:${HOST_BIND_PORT}`,由宿主机 Nginx 反向代理。
|
||||
- PostgreSQL/Redis 建议使用托管或远程实例,并通过白名单限制访问来源。
|
||||
- HTTPS 由宿主机 Nginx 统一终止,保留 SSE 反代配置(`proxy_buffering off`、长超时)。
|
||||
- 定时备份 Postgres:
|
||||
- `pg_dump` 每日一次,保留 7-14 天并异地存储。
|
||||
|
||||
## 8. 宿主机 Nginx 配置示例
|
||||
|
||||
将域名流量转发到本机 `127.0.0.1:${HOST_BIND_PORT}`(容器 app 端口),并确保 SSE 可用。
|
||||
|
||||
### 8.1 HTTP 示例
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name api.your-domain.com;
|
||||
|
||||
client_max_body_size 20m;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:${HOST_BIND_PORT};
|
||||
proxy_http_version 1.1;
|
||||
|
||||
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;
|
||||
|
||||
# SSE support
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
proxy_read_timeout 3600;
|
||||
proxy_send_timeout 3600;
|
||||
chunked_transfer_encoding off;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2 HTTPS 示例(推荐)
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name api.your-domain.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/api.your-domain.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/api.your-domain.com/privkey.pem;
|
||||
|
||||
client_max_body_size 20m;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:${HOST_BIND_PORT};
|
||||
proxy_http_version 1.1;
|
||||
|
||||
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;
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
proxy_read_timeout 3600;
|
||||
proxy_send_timeout 3600;
|
||||
chunked_transfer_encoding off;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
应用配置后执行:
|
||||
|
||||
```bash
|
||||
sudo nginx -t && sudo systemctl reload nginx
|
||||
```
|
||||
@@ -1,249 +0,0 @@
|
||||
# ChatOne Service 单机部署指南(Ubuntu + PM2 + Nginx)
|
||||
|
||||
本文给出 `chat-one-service` 在单机 Linux 环境的可执行部署流程,覆盖:
|
||||
- 服务器基线检查
|
||||
- 生产环境变量合同
|
||||
- 发布与回滚流程
|
||||
- Nginx 反向代理(含 SSE)
|
||||
- 监控、备份与巡检
|
||||
|
||||
## 1. 适用范围
|
||||
|
||||
- OS:Ubuntu 22.04 LTS
|
||||
- Runtime:Node.js 22.x
|
||||
- 进程管理:PM2
|
||||
- 反向代理:Nginx
|
||||
- 依赖:PostgreSQL、Redis(可为外部托管)
|
||||
|
||||
## 2. 服务器基线检查(部署前)
|
||||
|
||||
### 2.1 主机与网络
|
||||
|
||||
- [ ] 已准备公网域名(示例:`api.example.com`)
|
||||
- [ ] `22/80/443` 已开放
|
||||
- [ ] 应用端口(默认 `3000`)仅允许本机访问
|
||||
- [ ] 时区与 NTP 已校准(`timedatectl status`)
|
||||
|
||||
### 2.2 账号与权限
|
||||
|
||||
- [ ] 创建专用用户:`chatone`
|
||||
- [ ] 禁止 root 直登,仅 SSH Key 登录
|
||||
- [ ] `chatone` 拥有 `/srv/chat-one-service` 读写权限
|
||||
|
||||
### 2.3 依赖连通性
|
||||
|
||||
- [ ] PostgreSQL 可连接(`DATABASE_URL` 可用)
|
||||
- [ ] Redis 可连接(`REDIS_HOST/PORT` 可用)
|
||||
- [ ] 第三方 AI API Key 已可用(如 `QWEN_API_KEY`)
|
||||
|
||||
## 3. 目录约定
|
||||
|
||||
```bash
|
||||
/srv/chat-one-service/
|
||||
releases/
|
||||
20260423_120000/
|
||||
current -> /srv/chat-one-service/releases/20260423_120000
|
||||
shared/
|
||||
.env
|
||||
logs/
|
||||
```
|
||||
|
||||
初始化目录:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /srv/chat-one-service/{releases,shared/logs}
|
||||
sudo chown -R chatone:chatone /srv/chat-one-service
|
||||
```
|
||||
|
||||
## 4. 运行时安装
|
||||
|
||||
```bash
|
||||
# Node.js 22(nvm 方式,推荐)
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
|
||||
source ~/.nvm/nvm.sh
|
||||
nvm install 22
|
||||
nvm use 22
|
||||
|
||||
# Yarn + PM2
|
||||
npm i -g yarn pm2
|
||||
|
||||
# Nginx + certbot
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y nginx certbot python3-certbot-nginx postgresql-client redis-tools
|
||||
```
|
||||
|
||||
## 5. 生产环境变量合同(shared/.env)
|
||||
|
||||
在 `/srv/chat-one-service/shared/.env` 写入:
|
||||
|
||||
```dotenv
|
||||
# app
|
||||
NODE_ENV=production
|
||||
PORT=3000
|
||||
APP_NAME=chat-one-service
|
||||
|
||||
# jwt(至少 32 位随机串)
|
||||
JWT_ACCESS_SECRET=replace-with-long-random-string
|
||||
JWT_REFRESH_SECRET=replace-with-long-random-string
|
||||
JWT_ACCESS_EXPIRES_IN=2h
|
||||
JWT_REFRESH_EXPIRES_IN=30d
|
||||
|
||||
# database
|
||||
DATABASE_URL=postgresql://user:password@host:5432/chat_one?schema=public
|
||||
|
||||
# redis
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=
|
||||
REDIS_DB=0
|
||||
REDIS_KEY_PREFIX_CLIENT=chatone:client
|
||||
REDIS_KEY_PREFIX_ADMIN=chatone:admin
|
||||
|
||||
# ai
|
||||
QWEN_API_KEY=
|
||||
QWEN_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
|
||||
DEEPSEEK_API_KEY=
|
||||
VOLC_API_KEY=
|
||||
|
||||
# ai route
|
||||
AI_ROUTE_RETRY_TIMES=1
|
||||
AI_ROUTE_TIMEOUT_MS=45000
|
||||
```
|
||||
|
||||
安全要求:
|
||||
- `.env` 仅服务器本地保存,不入仓库。
|
||||
- 定期轮换密钥,变更后执行 `pm2 reload chat-one-service --update-env`。
|
||||
|
||||
## 6. 首次部署流程
|
||||
|
||||
以下命令以 `chatone` 用户执行:
|
||||
|
||||
```bash
|
||||
set -e
|
||||
APP_ROOT=/srv/chat-one-service
|
||||
RELEASE="$APP_ROOT/releases/$(date +%Y%m%d_%H%M%S)"
|
||||
|
||||
mkdir -p "$RELEASE"
|
||||
git clone <your-repo-url> "$RELEASE"
|
||||
cd "$RELEASE"
|
||||
|
||||
yarn install --frozen-lockfile
|
||||
yarn build
|
||||
npx prisma migrate deploy
|
||||
|
||||
ln -sfn "$RELEASE" "$APP_ROOT/current"
|
||||
```
|
||||
|
||||
启动:
|
||||
|
||||
```bash
|
||||
cd /srv/chat-one-service/current
|
||||
pm2 start ecosystem.config.js --env production
|
||||
pm2 save
|
||||
pm2 startup
|
||||
```
|
||||
|
||||
## 7. 日常发布流程(零停机)
|
||||
|
||||
```bash
|
||||
set -e
|
||||
APP_ROOT=/srv/chat-one-service
|
||||
RELEASE="$APP_ROOT/releases/$(date +%Y%m%d_%H%M%S)"
|
||||
|
||||
mkdir -p "$RELEASE"
|
||||
git clone <your-repo-url> "$RELEASE"
|
||||
cd "$RELEASE"
|
||||
|
||||
yarn install --frozen-lockfile
|
||||
yarn build
|
||||
npx prisma migrate deploy
|
||||
|
||||
ln -sfn "$RELEASE" "$APP_ROOT/current"
|
||||
pm2 reload chat-one-service --update-env
|
||||
```
|
||||
|
||||
发布后验证:
|
||||
|
||||
```bash
|
||||
curl -fsS http://127.0.0.1:3000/api/docs >/dev/null
|
||||
curl -fsS https://api.example.com/api/docs >/dev/null
|
||||
```
|
||||
|
||||
如需 SSE 冒烟测试,调用:
|
||||
- `POST /api/client/v1/chat/completions/stream`
|
||||
|
||||
## 8. Nginx 配置(含 SSE)
|
||||
|
||||
参考文件:`deploy/nginx/chat-one-service.conf`
|
||||
|
||||
生效步骤:
|
||||
|
||||
```bash
|
||||
sudo cp deploy/nginx/chat-one-service.conf /etc/nginx/sites-available/chat-one-service.conf
|
||||
sudo ln -sfn /etc/nginx/sites-available/chat-one-service.conf /etc/nginx/sites-enabled/chat-one-service.conf
|
||||
sudo nginx -t
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
申请 HTTPS:
|
||||
|
||||
```bash
|
||||
sudo certbot --nginx -d api.example.com
|
||||
```
|
||||
|
||||
## 9. 回滚策略
|
||||
|
||||
### 9.1 代码回滚(快速)
|
||||
|
||||
```bash
|
||||
APP_ROOT=/srv/chat-one-service
|
||||
ls -1dt "$APP_ROOT"/releases/* | sed -n '1,2p' # 找到上一个版本
|
||||
ln -sfn <previous-release-path> "$APP_ROOT/current"
|
||||
pm2 reload chat-one-service --update-env
|
||||
```
|
||||
|
||||
### 9.2 数据回滚(高风险)
|
||||
|
||||
- 仅在迁移引发严重问题时执行。
|
||||
- 使用最近一次全量备份恢复(建议维护停机窗口)。
|
||||
|
||||
## 10. 备份与监控最小集
|
||||
|
||||
### 10.1 PostgreSQL 备份
|
||||
|
||||
每日定时(cron):
|
||||
|
||||
```bash
|
||||
pg_dump "$DATABASE_URL" | gzip > /data/backup/chat_one_$(date +%F).sql.gz
|
||||
```
|
||||
|
||||
建议:
|
||||
- 保留 7-14 天
|
||||
- 同步到对象存储(异地)
|
||||
|
||||
### 10.2 应用观测
|
||||
|
||||
- PM2:重启次数、内存、CPU
|
||||
- Nginx:`4xx/5xx` 比率、延迟
|
||||
- Redis:连接数与内存
|
||||
- 日志:按天滚动,至少保留 7 天
|
||||
|
||||
## 11. 常用排障命令
|
||||
|
||||
```bash
|
||||
pm2 ls
|
||||
pm2 logs chat-one-service --lines 200
|
||||
pm2 describe chat-one-service
|
||||
|
||||
sudo systemctl status nginx
|
||||
sudo tail -n 200 /var/log/nginx/error.log
|
||||
|
||||
curl -i http://127.0.0.1:3000/api/docs
|
||||
```
|
||||
|
||||
## 12. 安全加固建议
|
||||
|
||||
- 安全组白名单限制 SSH 来源
|
||||
- 开启 UFW,仅放行 `22/80/443`
|
||||
- 禁止将 `.env`、备份明文文件提交到 Git
|
||||
- 配置 fail2ban(可选)
|
||||
Reference in New Issue
Block a user