Files
photo-live/docs/plans/2026-09-21-测试服务器部署方案.md
T
2026-09-21 10:27:02 +08:00

157 lines
6.8 KiB
Markdown
Raw 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.
# 测试服务器部署方案(国内 ECS · 单机双栈)
日期:2026-09-21 · 目标:把完整系统(cn 管理栈 + ov 观众栈)部署到国内测试 ECS,真实 OSS、可从外网访问、App/浏览器可联调。
服务器画像(已确认):国内阿里云 ECS,已装 1Panel + Docker + MySQL 容器。OSS 凭证已验证(G1 通过)。
**单机双栈说明**:cn 与 ov 两套栈同机部署——ov 的 MySQL 库(photo_ov)也建在同一 1Panel MySQL 实例里,sync 走本机回环连双库,**无需跨境链路**。功能与生产架构完全同构(观众走 ov、管理走 cn、跨境同步本机化),仅地域拆分这一维度被测试环境折叠。
---
## 0. 前置检查(2 分钟)
在 1Panel 终端执行:
```bash
# MySQL 版本必须 ≥ 8.0.30(utf8mb4_0900_bin 校对门槛,需求 §5/D12)
docker exec $(docker ps --format '{{.Names}}' | grep -i mysql | head -1) mysql -uroot -p'你的MySQL root密码' -e "SELECT VERSION();"
# Redis 是否已装(应用商店装一个即可,记下容器名)
docker ps --format '{{.Names}}' | grep -i redis || echo "需要装 Redis(1Panel 应用商店 → Redis,任意版本)"
```
版本 < 8.0.30 → 先升级 MySQL 容器或改用 utf8mb4_bin(改 infra 迁移脚本四处 CREATE TABLE 的 collation + 重建本地验证,通知我处理)。
## 1. 本地导出镜像(开发机执行)
```bash
cd /d/project/photo
TAG=test-20260921
docker build -f docker/server.Dockerfile -t photo-live-server:$TAG .
docker build -f docker/web.Dockerfile -t photo-live-web:$TAG .
docker save photo-live-server:$TAG photo-live-web:$TAG | gzip > /d/photo-live-$TAG.tar.gz
ls -lh /d/photo-live-$TAG.tar.gz # 约 700-900MB(gzip 后)
```
## 2. 传输与导入
```bash
# 开发机 → 服务器(1Panel 终端也能看 scp 命令;或用宝塔式上传到 /opt)
scp /d/photo-live-test-20260921.tar.gz root@<服务器IP>:/opt/
# 服务器上导入
docker load < /opt/photo-live-test-20260921.tar.gz
docker images | grep photo-live # 确认两个镜像
```
## 3. MySQL 建库授权(1Panel 终端)
```sql
-- 1Panel → 数据库 → 终端,或 docker exec 进 MySQL 容器
CREATE DATABASE photo_cn CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin;
CREATE DATABASE photo_ov CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin;
CREATE USER 'photo'@'%' IDENTIFIED BY '<给 photo 用户设一个强密码>';
GRANT ALL PRIVILEGES ON photo_cn.* TO 'photo'@'%';
GRANT ALL PRIVILEGES ON photo_ov.* TO 'photo'@'%';
FLUSH PRIVILEGES;
```
Redis:1Panel 应用商店装 Redis(无密码即可起步;容器在 1panel-network 网络里,服务经容器名访问)。
## 4. 目录与 env(服务器执行)
```bash
mkdir -p /opt/photo-live && cd /opt/photo-live
```
**`.env.cn`**(关键项;完整清单见仓库 `.env.production.example-cn`——复制后改以下值):
```env
# 数据库:容器名取决于 1Panel 实例名(docker ps 查,替换 mysql 的实际容器名)
DATABASE_URL_CN=mysql://photo:<上面设的密码>@<mysql容器名>:3306/photo_cn?connection_limit=10
DATABASE_URL_OV=mysql://photo:<密码>@<mysql容器名>:3306/photo_ov?connection_limit=10
REDIS_URL_CN=redis://<redis容器名>:6379
# OSS(G1 已验证的定案形态)
S3_ENDPOINT=https://oss-cn-beijing.aliyuncs.com
S3_REGION=oss-cn-beijing
S3_ACCESS_KEY=<你的AK>
S3_SECRET_KEY=<你的SK>
S3_BUCKET=live-album
S3_FORCE_PATH_STYLE=false
# 同步密钥(生成:openssl rand -hex 32)
SYNC_INTERNAL_KEY=<openssl rand -hex 32 的结果>
OV_API_URL=http://api-cn:8081 # 同机:sync 直连 api-ov 容器
CN_API_URL=http://api-cn:8080
PORT=8080
PORT_OV=8081
# 管理员种子
ADMIN_ACCOUNT=admin
ADMIN_PASSWORD=<设一个初始管理员密码>
# 测试环境:允许跨源(有正式域名后收窄)
CORS_ORIGINS=*
```
**`.env.ov`**:同文件的 OSS 段 + `DATABASE_URL_OV` + `REDIS_URL_OV=redis://<redis容器名>:6379` + `PORT_OV=8081`(完整清单见 `.env.production.example-ov`)。
## 5. 编排启动
把仓库的 `infra/deploy/docker-compose-cn.yml`、`docker-compose-ov.yml` 上传到 `/opt/photo-live/`,然后:
```bash
cd /opt/photo-live
# 1Panel → 容器 → 编排 → 创建 → 粘贴 compose 内容(界面化路径)
# 或命令行(compose 文件里 SERVER_IMAGE/WEB_IMAGE 环境变量指定 tag):
SERVER_IMAGE=photo-live-server:test-20260921 WEB_IMAGE=photo-live-web:test-20260921 \
docker compose -f docker-compose-cn.yml up -d
SERVER_IMAGE=photo-live-server:test-20260921 WEB_IMAGE=photo-live-web:test-20260921 \
docker compose -f docker-compose-ov.yml up -d
```
compose 默认连接 `1panel-network` 外部网络;若你的网络名不同(`docker network ls` 查),改 compose 尾部 networks 段。
## 6. 数据库迁移 + 管理员种子(一次性)
```bash
docker run --rm --network 1panel-network --env-file .env.cn \
photo-live-server:test-20260921 migrate-deploy all
docker run --rm --network 1panel-network --env-file .env.cn \
photo-live-server:test-20260921 seed-admin
```
## 7. 验证(冒烟四点)
```bash
# 服务器上:
bash scripts/prod-smoke.sh http://127.0.0.1:8080 http://127.0.0.1:8081 admin '<ADMIN_PASSWORD>'
# 开发机上(外网可达性;先在 ECS 安全组放行 8088/8089):
curl http://<服务器IP>:8088/v1/health
curl http://<服务器IP>:8089/v1/health
```
通过标志:四点全 PASS + 两个 health 返回 `{"status":"ok"}`。
## 8. 访问入口与联调
| 入口 | 地址 | 用途 |
|---|---|---|
| 观众页(走 ov 栈,真实观众链路) | `http://<IP>:8089/a/<token>` | 浏览/点赞/气泡/热门 |
| 管理后台(cn 栈) | `http://<IP>:8088/admin/` | 全功能后台 |
| 观众页(cn 只读形态) | `http://<IP>:8088/a/<token>` | 备用 |
| App | 构建时 `--dart-define API_BASE=http://<IP>:8080` 或装 debug 包后改配置 | 真机联调 |
| 嵌入组件 | 宿主页引 `http://<IP>:8089/embed/v1/loader.js` | 官网接入形态 |
后续上正式域名:1Panel → 网站 → OpenResty 反代 8088/8089 + 证书,env 的 CORS_ORIGINS 收窄为域名,无需改代码。
## 9. 安全与运维注意(测试环境基线)
- 安全组只放行 8088/8089(web);8080/8081/3306/6379 不对公网开放(web 容器同机反代 /v1)。
- `.env.cn/.env.ov` 权限 `chmod 600`;AK 建议按此前提醒在稳定后轮换。
- 日志:compose 已配 json-file 10m×3;看实时 `docker logs -f photo-api-cn`。
- 回滚:`SERVER_IMAGE` 换回旧 tag `docker compose up -d` 即可(迁移向前兼容原则,详见 RUNBOOK.md)。
---
## 执行分工(二选一)
- **你执行**:按 0→8 逐步粘贴(约 30-40 分钟,大头是镜像传输);卡在任何一步叫我。
- **我执行**:提供 SSH 访问方式(密钥/密码经安全渠道),我在服务器上跑完全部步骤并回报冒烟结果;镜像 tar 我先在本机备好。