Files
photo-live/infra/deploy/docker-compose.cn.yml
T
浅念 250d4355b9 build(deploy): production images, compose stacks and 1panel guide
P5-prep Task 1(docs/plans/2026-09-21-P5-准备件.md):

- docker/server.Dockerfile:单镜像 photo-live-server 多角色(api-cn/api-ov/
  worker/sync/migrate-deploy/seed-admin,entrypoint.sh 分发;migrate-deploy
  支持 cn|ov|all 区域参数)。三阶段:全量 install(锁文件冻结)→ prisma
  generate 双库 + 逐包构建;--prod 依赖层;runtime=node:20-alpine+openssl/curl
  + 全局 prisma@5.22.0(对齐锁文件)+ 双库 client 镜像内重建(db-cn 落 pnpm
  store .prisma、db-ov 落包内 generated/)。sharp 走 musl 预编译验证通过。
- docker/web.Dockerfile + infra/deploy/nginx.conf.template:photo-live-web
  (nginx:alpine + envsubst 模板)。viewer(/,history 回退) + admin(/admin/,
  hash 路由) + /v1 反代 API_UPSTREAM(含 /v1/realtime WS 升级)+
  /assets/、/admin/assets/、/embed/v1/ immutable 长缓存(admin assets 的
  alias 前缀剥除坑已实测修复)。VITE_* 为构建期参数(VIEWER_BASE/
  EMBED_ORIGIN 随域名构建传入)。
- infra/deploy/docker-compose.cn.yml / -ov.yml:cn=api-cn+worker+sync+web,
  ov=api-ov+web-ov(核实架构:sync 仅 cn 侧,inbox/emergency 内嵌 api-ov,
  无 ov 侧 sync 进程);健康检查 /v1/health、unless-stopped、json-file
  10m×3、外部 1panel-network 复用 1Panel MySQL/Redis、SERVER_IMAGE/
  WEB_IMAGE 环境变量化镜像 tag(回滚杠杆)。
- .env.production.example-cn/-ov:生产变量全量清单(cn 25 键/ov 24 键,
  DB/Redis/OSS/SYNC/AUTH/限速/域名分组注释,源自 services+packages
  process.env 全量审计);.gitignore 放行 example,真实 .env.production-*
  永不入库。
- infra/deploy/README-1Panel.md:镜像导入双路径(save tar 导入 / 仓库 pull)、
  MySQL 建库授权 SQL(utf8mb4_0900_bin,<8.0.30 回退 utf8mb4_bin——D12)、
  Redis 连接、1Panel 编排、OpenResty 反代+证书、migrate-deploy 一次性容器、
  首次部署顺序(DB→迁移→ov 栈→cn 栈→seed→冒烟)。
- 根 package.json pnpm.onlyBuiltDependencies 增补 sharp/prisma/@prisma/
  engines/@prisma/client(镜像构建所需 install 脚本白名单)。

本地验证:两镜像构建成功(server 988MB / web 97.7MB);compose config 校验
通过;server 镜像内逐服务 require(sharp/argon2/双 Prisma client/bullmq/
ioredis)与双引擎 so.node、migrate-deploy 角色、无 .env 泄漏均实测;web 镜像
容器实测路由(viewer 回退/admin 子路径/assets 与 embed immutable/WS 代理路径
502 语义)全通过。未起真实栈(无真实 DB,符合准备件边界)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-21 01:39:55 +08:00

89 lines
3.3 KiB
YAML
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.
# infra/deploy/docker-compose.cn.yml —— 国内(cn)生产编排(P5-prep Task 1)。
# 角色:api-cn(写路径 API)/ worker(sharp 变体流水线 + 发布事务 outbox)/
# sync(outbox→ov 推送 + 对账 + 统计回传,双库直连)/ web(nginx 网关)。
# 架构核实:sync 是独立进程跑在 cn 侧(services/sync/src/main.ts 双库连接);
# ov 侧无任何 sync 进程(inbox 内嵌 api-ov,见 docker-compose-ov.yml)。
#
# 使用(1Panel 容器→编排→新建编排,或 docker compose -f 本文件 up -d):
# 1. 同目录放 .env.production-cn(模板见仓库根 .env.production.example-cn)。
# 2. 镜像已导入(README-1Panel.md §1);SERVER_IMAGE/WEB_IMAGE 可用环境变量
# 覆盖 tag(回滚 = 指回旧 tag 后 up -d,见 RUNBOOK.md)。
# 3. 网络默认挂外部 1panel-network 以便用容器名直连 1Panel 的 MySQL/Redis;
# 若你的 1Panel 网络名不同,或打算用宿主机 IP + 端口连接,把下方 networks
# 整段换成普通桥接网络(photo-net: {})并同步改 .env 里的连接串 host。
#
# 首次部署顺序(迁移先于 API):README-1Panel.md §7。
name: photo-live-cn
x-server-image: &server-image ${SERVER_IMAGE:-photo-live-server:latest}
x-logging: &default-logging
driver: json-file
options: { max-size: "10m", max-file: "3" }
services:
api-cn:
image: *server-image
command: ["api-cn"]
init: true
env_file: .env.production-cn
environment:
PORT: "8080" # 容器内固定;对外经 web 反代或 OpenResty
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-fs", "http://127.0.0.1:8080/v1/health"]
interval: 30s
timeout: 5s
retries: 5
start_period: 20s
logging: *default-logging
networks: [photo-net]
worker:
image: *server-image
command: ["worker"]
init: true
env_file: .env.production-cn
# 无 HTTP 端口:健康面由 restart 策略 + 日志监控承担(RUNBOOK.md 故障速查)。
restart: unless-stopped
logging: *default-logging
networks: [photo-net]
sync:
image: *server-image
command: ["sync"]
init: true
env_file: .env.production-cn
# 需要额外可达:OV_API_URL(公网域名)与 DATABASE_URL_OV(ov MySQL,跨地域)。
restart: unless-stopped
logging: *default-logging
networks: [photo-net]
web:
image: ${WEB_IMAGE:-photo-live-web:latest}
init: true
environment:
API_UPSTREAM: http://api-cn:8080 # /v1 反代目标(含 WS /v1/realtime)
ports:
# 只绑本机回环:1Panel OpenResty(同宿主机)反代到 127.0.0.1:8088;
# OpenResty 在其它机器时改为 "8088:80" 并配防火墙白名单。
- "127.0.0.1:8088:80"
restart: unless-stopped
depends_on:
api-cn: { condition: service_healthy }
healthcheck:
test: ["CMD", "curl", "-fs", "http://127.0.0.1/"]
interval: 30s
timeout: 5s
retries: 5
start_period: 10s
logging: *default-logging
networks: [photo-net]
networks:
photo-net:
# 复用 1Panel 应用网络(其名通常为 1panel-network):容器名互通 MySQL/Redis。
# 若网络名不同:name 改实际名。若走宿主机 IP 连接:整段替换为 `photo-net: {}`。
name: 1panel-network
external: true