# 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: . # 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 # G4 §4.8 事件 B:最新 digest 的 10-listen-on-ipv6 entrypoint 在服务器卡死 # (nginx 不启动、healthcheck 拒连)——构建期移除该脚本(本地旧 digest 无此问题, # 服务器新拉必现)。钉基础镜像版本后可移除本行(待办 G4 登记)。 RUN rm -f /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh # 官方镜像启动时 envsubst 渲染 /etc/nginx/templates/*.template → conf.d; # API_UPSTREAM 由 compose environment 注入(缺省指向 cn API 容器名)。 ENV API_UPSTREAM=http://api-cn:8080 # 根路径跳转目标(cn 默认进后台;ov 栈 compose 覆盖为 /index.html 安全自指)。 ENV ROOT_REDIRECT=/admin/ 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