Files
photo-live/docker/web.Dockerfile
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

67 lines
3.3 KiB
Docker
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.
# syntax=docker/dockerfile:1
# docker/web.Dockerfile —— photo-live-web 前端网关镜像(P5-prep Task 1)。
# nginx:alpine 承载 viewer(/,history 路由)+ admin(/admin/,hash 路由)
# + /v1 反代 API(API_UPSTREAM env,含 /v1/realtime WS 升级)
# + /embed/v1/ 与 /assets/ 内容寻址长缓存(见 infra/deploy/nginx.conf.template)。
#
# 构建(VITE_* 为构建期变量——viewer/admin 的 API 基址在产物内固化):
# docker build -f docker/web.Dockerfile \
# --build-arg VITE_VIEWER_BASE=https://viewer.example.com \
# --build-arg VITE_EMBED_ORIGIN=https://viewer.example.com \
# -t photo-live-web:<tag> .
# VITE_API_BASE 缺省空串(同源 /v1,经本镜像 nginx 反代)——cn/ov 两地域共用
# 同一构建参数集,API 差异全部由运行时 API_UPSTREAM 承担。
# ── 阶段 1:构建 ──
FROM node:20-alpine AS build
WORKDIR /app
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
RUN corepack enable
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY apps/admin/package.json apps/admin/
COPY apps/viewer/package.json apps/viewer/
COPY packages/contracts/package.json packages/contracts/
COPY packages/db-cn/package.json packages/db-cn/
COPY packages/db-ov/package.json packages/db-ov/
COPY packages/embed-loader/package.json packages/embed-loader/
COPY packages/storage/package.json packages/storage/
COPY services/api/package.json services/api/
COPY services/sync/package.json services/sync/
COPY services/worker/package.json services/worker/
RUN --mount=type=cache,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile
COPY packages packages
COPY apps apps
# 构建期 VITE 变量(进程 env 优先级高于 apps/*/.env* 文件):
# VITE_API_BASE viewer API 基址;空串=同源相对路径(生产网关形态,缺省)。
# VITE_BASE_URL admin 资源前缀=/admin/(nginx 子路径挂载;hash 路由)。
# VITE_VIEWER_BASE / VITE_EMBED_ORIGIN admin「分享卡/嵌入代码」拼 URL 用,
# 随真实域名构建时传入(缺省 dev 兜底仅作占位)。
ARG VITE_API_BASE=""
ARG VITE_BASE_URL=/admin/
ARG VITE_VERSION=0.1.0
ARG VITE_VIEWER_BASE=http://127.0.0.1:5175
ARG VITE_EMBED_ORIGIN=http://127.0.0.1:5175
ENV VITE_API_BASE=${VITE_API_BASE} \
VITE_BASE_URL=${VITE_BASE_URL} \
VITE_VERSION=${VITE_VERSION} \
VITE_VIEWER_BASE=${VITE_VIEWER_BASE} \
VITE_EMBED_ORIGIN=${VITE_EMBED_ORIGIN}
# embed-loader 先构建并同步进 viewer publicDir(loader.js 内容寻址路径 /embed/v1/),
# 随后 viewer / admin 构建(contracts 是两者的类型/运行时依赖,先出 dist)。
RUN pnpm --filter @photo/contracts run build \
&& pnpm --filter @photo/embed-loader run build \
&& pnpm --filter @photo/embed-loader run sync \
&& pnpm --filter @photo/viewer run build \
&& pnpm --filter @photo/admin run build
# ── 阶段 2:nginx ──
FROM nginx:alpine
# 官方镜像启动时 envsubst 渲染 /etc/nginx/templates/*.template → conf.d;
# API_UPSTREAM 由 compose environment 注入(缺省指向 cn API 容器名)。
ENV API_UPSTREAM=http://api-cn:8080
COPY infra/deploy/nginx.conf.template /etc/nginx/templates/default.conf.template
COPY --from=build /app/apps/viewer/dist /usr/share/nginx/html/viewer
COPY --from=build /app/apps/admin/dist /usr/share/nginx/html/admin
EXPOSE 80