# 觅爻生产部署指南 ## 目录说明 `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_REPOSITORY= ``` 如果本目录下的 `.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 ``` ## 更新版本 当前 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 旧镜像不会被清空。 如需手动更新,在生产机器执行: ```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" ```