e5302e3929
Co-Authored-By: Claude Code <noreply@anthropic.com>
12 KiB
12 KiB
2026-09-24 正式环境双地域部署(P5 生产上线)
状态:已执行完毕(2026-09-24,验收记录见 progress/正式环境双地域部署-验收记录.md)。 输入:用户 2026-09-24 指令;记忆双地域方案(跨境 HMAC 同步 + 安全组互白名单 + 全新空库 + 域名证书);G4 验收记录 §4.6/§4.8 全部坑位经验。 用户已拍板(2026-09-24):hnxinyouhe.com 已备案(cn 直接域名+HTTPS); 不接 CDN(A25「图片经全球 CDN」暂不满足,如实标注);OSS 复用现有桶 (G1 凭证,从测试服务器 env 取)。
0. 现状侦察结论(2026-09-24)
SSH 通道
| 机 | IP | 通道 | 状态 |
|---|---|---|---|
| ov 境外 | 47.254.176.10 | 本机 → ProxyJump root@8.152.213.143(跳板在 ov 安全组白名单)→ root,钥匙 ~/.ssh/id_ed25519(即 cms-cj-deploy,ov 机已装过) |
✅ 已通 |
| cn 国内 | 101.37.116.184 | 本机直连 root + 同一把钥匙 | ⏳ 等公钥装入 authorized_keys(用户进行中) |
| 跳板(老国内机) | 8.152.213.143 | 本机直连 root + 同钥匙 | ✅ 已通 |
写入 ~/.ssh/config:photo-ov(带 ProxyJump)/ photo-cn 两个 Host 条目。
ov 机探测(已完成)
- Debian 13 / 2C / 7.4G / 40G 盘 83% 用(剩 6.5G +
docker builder prune可回收 ~2G → 部署前清一次,够用) - Docker 29.4 + Compose v5.1.3;Docker Hub 直连正常(registry-1.docker.io 401=通)
- NTP 已同步(阿里云内部 NTP,Stratum 3)——HMAC ±300s 防重放硬前提 ✓
- 出网:aliyun intl / docker hub / gitea:25311(0.58s) / oss-hangzhou 全通
- 跨境:ov→cn 22/443 TCP 可达 ✓
- DNS:inside→cn、outside→ov 解析正确 ✓
- 机上已有:1Panel 全家桶(OpenResty 占 80/443、MySQL 5.7.44@127.0.0.1:3306、Redis 8.6.2、phpMyAdmin 占 8089、php-fpm)+ tracker / cc-ai-kefu / cms-cj 等项目
- 本机命令样例:
ssh photo-ov '…'/scp … photo-ov:/opt/…
坑位(G4 §4.6/§4.8 经验,全部纳入流程)
- web 容器随 api 容器重建后必须一并 restart(nginx 缓存旧上游容器 IP → 502)。
nginx:alpine最新 digest 的 10-listen-on-ipv6 entrypoint 卡死——本次 T0 把补丁行正式进仓库 Dockerfile。- 本机 Docker Hub 抽风预案:构建挪服务器(ov 直连 Hub;cn 若不通走 1Panel 加速器,探测时确认
/etc/docker/daemon.json)。 - MySQL 8.4
trigger/cursor为保留字,手工 SQL 全部反引号。 .env.production-*chmod 600、不入库不入镜像。
1. 目标形态
cn 101.37.116.184 (live-album.inside.hnxinyouhe.com, 已备案)
└ photo-live-cn 栈:api-cn / worker / sync / web + 自管 mysql:8.4 + redis:7
ov 47.254.176.10 (live-album.outside.hnxinyouhe.com)
└ photo-live-ov 栈:api-ov / web-ov + 自管 mysql:8.4 + redis:7
跨境链路:
sync 推送/对账:cn sync → https://live-album.outside.hnxinyouhe.com(HMAC)
统计回传读库:cn sync → 47.254.176.10:13306(ov mysql,安全组仅放行 cn IP)
入口:两机各自 1Panel OpenResty 建站点 → 反代 127.0.0.1 回环端口 → Let's Encrypt 证书
2. 任务序
T0 仓库准备(本机,先行)
docker/web.Dockerfile:FROM nginx:alpine后加RUN rm -f /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh(§4.8 事件 B 补丁正式化,钉版本列为后续待办)。- 服务器 compose 适配(两台各自
/opt/photo-live/deploy/,不进仓库):基于infra/deploy/docker-compose-ov.yml/-cn.yml改三点—— ① web 主机端口:ov127.0.0.1:18089(8089 被 phpMyAdmin 占),cn127.0.0.1:18088(避冲突统一 18xxx); ② 增自管服务mysql(mysql:8.4 + utf8mb4_0900_bin + named volume)与redis(redis:7-alpine); ③ 网络改独立桥photo-net(不挂 1panel-network——不复用 1Panel 的 MySQL5.7/Redis)。 ov mysql 额外映射0.0.0.0:13306:3306(跨境 sync 读库,安全组仅放行 cn IP)。 - commit + push gitea(两台服务器
git pull用)。 - 验收:flutter/后端零改动,
docker build本机两镜像可构建(顺带验证 Hub 状态)。
T1 cn 环境探测(公钥装入后立即)
- 跑与 ov 同一份探测脚本(.tmp-probe.sh):规格/系统/Docker/Compose/加速器/MySQL/NTP/时区/端口占用/出网(Hub、gitea、uniservice、oss)/跨境 cn→ov TCP。
- 决定 cn 构建路径(本机构建传输 vs 服务器构建)与磁盘是否需清理。
- 验收:探测记录回填本文档 §0;cn 18088/13306 无端口冲突或改用其它高位端口。
T2 ov 栈部署(先 ov——cn 的 sync 依赖 ov API 可达)
mkdir -p /opt/photo-live/{src,deploy};clone gitea(凭证用令牌,clone 后 remote 去掉令牌或用 deploy 方式)。docker builder prune -f(回收 ~2G)。- 写
.env.production-ov(600,全新值):DATABASE_URL_OV=mysql://photo_ov:<新强密码>@mysql:3306/photo_ov?connection_limit=10REDIS_URL_OV=redis://redis:6379- S3 四元组:从测试服务器
/opt/photo-live/deploy/.env.production-cn抄 G1 真实值(同桶同凭证,ov 只读现签) CORS_ORIGINS=https://live-album.outside.hnxinyouhe.comSYNC_INTERNAL_KEY=<openssl rand -hex 32 新生成,与 cn 同值>- 互动/限速参数按模板缺省
- mysql 容器起后建库建账号:
CREATE DATABASE photo_ov CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin;CREATE USER 'photo_ov'@'%' …GRANT ON photo_ov.*(安全组收口;sync 专用账号photo_ov_sync@101.37.116.184后续可拆,首期单账号+% 靠安全组白名单)。 - 构建/导入镜像(按 T0 验证结果选路径):
- 路径 A:本机
docker build→ save/gzip →scp -J root@8.152.213.143直达 ov →docker load - 路径 B(本机 Hub 抽风):源码已在
/opt/photo-live/src(git pull)→ ov 服务器docker build(Hub 直连已验证 OK) - tag 约定
<git短sha>-20260924(当前 d331d55,若 T0 有新提交以新 sha 为准);web ov 版带VITE_VIEWER_BASE=https://live-album.outside.hnxinyouhe.com
- 路径 A:本机
docker compose … run --rm <server image> migrate-deploy ov(迁移先于 API)。SERVER_IMAGE=… WEB_IMAGE=… docker compose -f docker-compose-ov.yml up -d;health{"status":"ok"}。- 1Panel 建网站
live-album.outside.hnxinyouhe.com→ 反代127.0.0.1:18089→ Let's Encrypt 证书(HTTP-01,80 已开)→ 强制 HTTPS;反代配置确认 WebSocket 透传(/v1/realtime Upgrade 头;1Panel 反代开 websocket 选项或手补proxy_set_header Upgrade/Connection)。 - 外网验证:
https://live-album.outside.hnxinyouhe.com/v1/health+ 观众页 404 兜底正常。
- 验收:HTTPS 入口通、api-ov healthy、(无数据期)公开端点空态正常。
- 回滚:
docker compose down;全新空库无数据风险;1Panel 站点删除。
T3 cn 栈部署
- 同 T2 建目录/clone/探测磁盘。
.env.production-cn(600,全新值):DATABASE_URL_CN/REDIS_URL_CN→ 自管容器DATABASE_URL_OV=mysql://photo_ov:<ov应用账号密码>@47.254.176.10:13306/photo_ov?connection_limit=10(跨公网直连 ov mysql)- S3 同桶同凭证;
CORS_ORIGINS=https://live-album.inside.hnxinyouhe.com SYNC_INTERNAL_KEY同 ov;CN_API_URL=http://api-cn:8080;OV_API_URL=https://live-album.outside.hnxinyouhe.comUSER_SYNC_SOURCE=http+ uniservice URL/KEY(从测试服务器 env 抄真实值)SYNC_USERS_INTERVAL_MS=43200000(12h,用户既定指令)ADMIN_ACCOUNT=admin+ADMIN_PASSWORD=<新强密码>(seed 后交付用户,建议首次登录即改)
- mysql 建库 photo_cn(同 collate)+ 账号。
- 镜像同 T2(web cn 版
VITE_VIEWER_BASE=https://live-album.inside.hnxinyouhe.com)。 migrate-deploy cn→seed-admin→up -d(api-cn/worker/sync/web)。- sync 日志核对:推送循环启动、连 ov inbox 通(若 ov API 443 未就绪会重试——T2 已先行则应直通)。
- 1Panel 建站点
live-album.inside.hnxinyouhe.com→ 反代127.0.0.1:18088→ 证书(已备案,HTTP-01 可过)→ 强制 HTTPS + WS 透传。 - 重建 api 后 restart web 容器(坑位 ①)。
- 验收:后台可登录(新密码)、health OK、sync 无连接错误。
- 回滚:同 T2;RUNBOOK 换旧 tag。
T4 跨境链路验证(依赖用户安全组操作)
用户在阿里云控制台操作(唯一外部依赖):
- ov 安全组:入方向放行
TCP/13306 ← 101.37.116.184(sync 读 ov 库); 建议加TCP/22 ← 101.37.116.184(cn→ov 备用 SSH 通道)。 - cn 安全组:确认 80/443 公网放行(站点要通)。
验证序:
- cn 容器内
mysql -h 47.254.176.10 -P 13306连通(或 nc 探测)。 - 全链路:后台建相册→上传测试照片→worker 出变体→outbox→sync 推送(~2s)→
ov 公开页
https://live-album.outside…/a/<token>看到照片、图片 presigned OSS URL 可加载。 - 反向:ov 页点赞→统计回传 60s→cn 库计数增长。
- 对账循环日志(5min 周期无 diff)。
scripts/prod-smoke.sh四点冒烟 + CORS 收窄 curl 验证(第三方 Origin 拒)。- uniservice 定时同步:首批手动触发(12h 间隔下重启后首批要等——用后台「手动同步」按钮)。
T5 收尾
- 验收记录
docs/plans/progress/落档(含坑位新增、A25 CDN 标注、跨境外网实测数据)。 - 密钥交付:
.env.production-*真实文件留存两台服务器(600)+ 本机工作区(.gitignore 已排除);ADMIN 密码/DB 密码清单单独交用户保管。 - 监控:
infra/deploy/monitoring.md告警项按现状裁剪接入(可后置)。
3. 密钥与凭据清单(全部新生成,唯一复用 = OSS/uniservice)
| 项 | 来源 | 存放 |
|---|---|---|
| SYNC_INTERNAL_KEY | openssl rand -hex 32 新生成 |
两端 .env(600) |
| mysql root / photo_cn / photo_ov 应用账号密码 | 新生成 | 各机 .env + mysql |
| ADMIN_PASSWORD | 新强密码 | cn .env + 交付用户 |
| S3 四元组(同桶) | 测试服务器 env 抄 | 两端 .env |
| OPEN_API_USERS_URL/KEY | 测试服务器 env 抄 | cn .env |
4. 风险与预案
| 风险 | 预案 |
|---|---|
| 本机 Docker Hub 抽风(§4.8 事件 A 复发) | 路径 B 服务器构建(ov 已验证 Hub 直连;cn 走加速器) |
| ov 磁盘 6.5G 紧张 | 部署前 builder prune(~2G);mysql/redis/server/web 镜像+库合计估 ~3G,余量足够;超预期则报告用户扩容 |
| 1Panel 反代丢 WS 头 | 手补 Upgrade/Connection 两行;实测 /v1/realtime 握手 |
| 跨境 13306 被扫 | 高位端口 + 安全组单 IP 白名单 + 账号强密码;后续可加 REQUIRE SSL |
| cn 公钥迟迟未装 | T1-T3 的 cn 部分阻塞,但 T2 ov 全部可先行(本计划顺序已兼容) |
| 测试服务器不受影响 | 全新机器全新库,零接触;gitea 仅读 |
5. 与准备件的偏差登记(部署后回填 RUNBOOK/README)
- compose 自管 mysql:8.4/redis(1Panel MySQL 是 5.7.44 不满足 utf8mb4_0900_bin/8.4 基线),独立 photo-net 网络。
- web 回环端口 18089/18088(8089 与 phpMyAdmin 冲突;18xxx 统一)。
- ov mysql 公网映射 13306(模板未含,跨境 sync 读库需要——白名单+SSL 待实测定案项落地)。
docker/web.Dockerfileentrypoint 补丁正式化(钉 nginx 版本仍为待办)。- CDN 不接(用户拍板);OSS 复用 G1 桶(用户拍板)。