Files

324 lines
7.2 KiB
Markdown
Raw Permalink Normal View History

# 觅爻生产部署指南
## 目录说明
`deploy/` 用于存放生产环境启动所需文件:
- `docker-compose.prod.yml`:生产 Docker Compose 启动配置,只拉取已有镜像,不负责构建。
- `.env`:生产环境变量文件,本文件包含敏感信息,不应提交到 Git。
## 前置条件
生产机器需要安装:
- Docker
- Docker Compose v2
- AWS CLI v2
- Node.js 22+ (前端 SSR 服务)
- PM2 (前端进程管理)
确认命令:
```bash
docker --version
docker compose version
aws --version
node --version # 需要 >= 22.12.0
pm2 --version
```
## 服务架构
生产环境运行以下服务:
| 服务 | 端口 | 说明 |
|------|------|------|
| Nginx | 80, 443 | 反向代理,SSL 终结 |
| 前端 SSR | 4322 | Node.js + Astro SSR |
| 后端 API | 5775 | Docker 容器 |
| Redis | 6379 | Docker 容器 |
| Worker Agent | - | Docker 容器 |
### 端口映射
```
Internet → Nginx (443)
├── /_astro/* → 静态文件 (client 目录)
├── /images/* → 静态文件 (client 目录)
└── /* → 反向代理到 localhost:4322 (前端 SSR)
前端 SSR (4322) → /api/* → 反向代理到 localhost:5775 (后端 API)
```
## 环境变量
`docker-compose.prod.yml` 默认从当前目录读取 `.env`
```bash
deploy/.env
```
必须包含 AWS ECR 镜像定位变量:
```text
AWS_ACCOUNT_ID=<你的 AWS 账号 ID>
AWS_REGION=<ECR 所在区域>
ECR_REPOSITORY=<ECR 仓库名>
```
如果本目录下的 `.env` 是从项目根目录 `.env` 复制过来的,通常还需要手动追加以上三个变量。
默认镜像地址会拼接为:
```text
${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${ECR_REPOSITORY}:latest
```
如果要手动指定完整镜像地址,可以在 `.env` 中设置:
```text
ERYAO_BACKEND_IMAGE=<完整镜像地址>
```
Web 服务端口使用项目环境变量:
```text
ERYAO_WEB__PORT=5775
```
默认只绑定本机回环地址:
```text
ERYAO_DEPLOY_BIND_HOST=127.0.0.1
```
如果生产机器没有 Nginx、ALB 或其他反向代理,需要直接对外暴露端口,可改为:
```text
ERYAO_DEPLOY_BIND_HOST=0.0.0.0
```
### 进程配置建议
生产 Compose 只启动一个 `worker-agent` 容器。Agent 任务、低频通用任务和反馈日报任务共用 `agent` 队列,不再单独常驻 `worker-general` 进程。
2 核 2G 机器建议使用:
```text
ERYAO_WEB__WORKERS=1
ERYAO_WORKER__GROUPS__AGENT__CONCURRENCY=2
```
4G 以上机器可按流量提高 Web 或 Agent worker 数量:
```text
ERYAO_WEB__WORKERS=2
ERYAO_WORKER__GROUPS__AGENT__CONCURRENCY=2
```
## 登录 ECR
进入部署目录,并把 `.env` 加载到当前 shell
```bash
cd deploy
set -a
. ./.env
set +a
```
在生产机器上配置好 AWS 凭据后执行:
```bash
aws ecr get-login-password --region "$AWS_REGION" \
| docker login --username AWS --password-stdin \
"${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com"
```
## 启动服务
启动 Web、Redis 和 worker
```bash
cd deploy
docker compose --env-file ./.env -f docker-compose.prod.yml --profile workers pull
docker compose --env-file ./.env -f docker-compose.prod.yml --profile workers up -d
```
只启动 Web 和 Redis
```bash
cd deploy
docker compose --env-file ./.env -f docker-compose.prod.yml up -d
```
## 健康检查
如果 `ERYAO_WEB__PORT=5775`
```bash
curl http://127.0.0.1:5775/health
```
期望返回:
```json
{"status":"ok"}
```
## 查看状态和日志
```bash
cd deploy
docker compose --env-file ./.env -f docker-compose.prod.yml --profile workers ps
docker logs -f eryao-prod-backend
docker logs -f eryao-prod-worker-agent
docker logs -f eryao-prod-redis
```
## 更新版本
2026-04-30 11:02:37 +08:00
当前 CI/CD 会在 `main` 分支构建后自动部署到生产机器:
- 推送前清空 ECR 仓库旧镜像,只保留新推送的 `latest`
- 通过 `DEPLOY_SSH_KEY` 登录生产机器。
- 在生产机器执行 ECR 登录、`docker compose pull``docker compose up -d`
- 健康检查通过后清理 7 天前未使用的本地 Docker 镜像。
Gitea Secrets 需要包含:
```text
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_REGION
AWS_ACCOUNT_ID
ECR_REPOSITORY
DEPLOY_SSH_KEY
DEPLOY_HOST
DEPLOY_USER
```
`DEPLOY_SSH_KEY` 是已加入生产机器 `ubuntu` 用户 `~/.ssh/authorized_keys` 的部署专用私钥。
当前生产机器对应:`DEPLOY_HOST=18.218.38.213``DEPLOY_USER=ubuntu`
CI 的 AWS 用户需要至少允许 ECR 登录、建仓库、推送镜像、列出镜像,以及为了覆盖式清理旧镜像所需的 `ecr:BatchDeleteImage`。如果缺少 `ecr:BatchDeleteImage`,部署仍可继续推送 `latest`,但 ECR 旧镜像不会被清空。
2026-04-30 11:02:37 +08:00
如需手动更新,在生产机器执行:
```bash
cd deploy
docker compose --env-file ./.env -f docker-compose.prod.yml --profile workers pull
docker compose --env-file ./.env -f docker-compose.prod.yml --profile workers up -d
```
## 停止服务
```bash
cd deploy
docker compose --env-file ./.env -f docker-compose.prod.yml --profile workers down
```
如需连 Redis 数据卷一起删除:
```bash
cd deploy
docker compose --env-file ./.env -f docker-compose.prod.yml --profile workers down -v
```
谨慎使用 `down -v`,它会删除 Redis 持久化数据。
## 前端部署
### 构建前端
在本地开发机器上:
```bash
cd web
PUBLIC_API_URL=https://api.meeyao.com npm run build
```
构建产物在 `web/dist/` 目录:
- `dist/client/` - 静态资源 (CSS, JS, 图片)
- `dist/server/` - SSR 服务端代码
### 上传到服务器
```bash
# 上传构建产物
rsync -avz -e "ssh -i xunmee.pem" web/dist/ ubuntu@18.218.38.213:/home/ubuntu/deploy/web/
# 上传依赖配置
rsync -avz -e "ssh -i xunmee.pem" web/package.json web/package-lock.json ubuntu@18.218.38.213:/home/ubuntu/deploy/web/
# 安装生产依赖
ssh -i xunmee.pem ubuntu@18.218.38.213 "cd /home/ubuntu/deploy/web && npm install --omit=dev"
```
### PM2 管理
```bash
# 启动服务
pm2 start server/entry.mjs --name meeyao-web
# 设置端口 (默认 4321,需要改为 4322)
export HOST=0.0.0.0
export PORT=4322
pm2 restart meeyao-web
# 保存进程列表 (开机自启)
pm2 save
# 查看状态
pm2 status
# 查看日志
pm2 logs meeyao-web
```
### Nginx 配置
前端 SSR 服务监听 `localhost:4322`Nginx 配置要点:
```nginx
server {
listen 443 ssl http2;
server_name meeyao.com;
# 静态资源直接从 client 目录提供
location /_astro {
root /home/ubuntu/deploy/web/client;
expires 30d;
add_header Cache-Control "public, immutable";
}
location /images {
root /home/ubuntu/deploy/web/client;
expires 30d;
}
# 其他请求代理到 Node.js SSR
location / {
proxy_pass http://127.0.0.1:4322;
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;
}
}
```
### 前端更新流程
```bash
# 1. 本地构建
cd web && PUBLIC_API_URL=https://api.meeyao.com npm run build
# 2. 上传
rsync -avz -e "ssh -i xunmee.pem" dist/ ubuntu@18.218.38.213:/home/ubuntu/deploy/web/
# 3. 重启服务
ssh -i xunmee.pem ubuntu@18.218.38.213 "pm2 restart meeyao-web"
```