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

6.8 KiB
Raw Permalink Blame History

测试服务器部署方案(国内 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 终端执行:

# 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. 本地导出镜像(开发机执行)

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. 传输与导入

# 开发机 → 服务器(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 终端)

-- 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(服务器执行)

mkdir -p /opt/photo-live && cd /opt/photo-live

.env.cn(关键项;完整清单见仓库 .env.production.example-cn——复制后改以下值):

# 数据库:容器名取决于 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/,然后:

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. 数据库迁移 + 管理员种子(一次性)

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 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 我先在本机备好。