Files
novalon-website/Dockerfile
T
zhangxiang a0328a623f chore(qa): 验收台账与证据入库 + 构建/部署配置同步
- docs/acceptance/qa-tracker.md:跨周期缺陷单一真源台账(§7=第五轮)。
- 周期 1/2 + iPhone SE/axe 验收证据目录、ACCEPTANCE_REVIEW 快照入库。
- 同步 README/CONTEXT/CLAUDE/DESIGN/testing/deployment/lessons-learned 口径;
  next.config/Dockerfile/nginx/Jenkinsfile/docker-compose/sentry/prisma 对齐
  standalone 产物装配与部署形态。
2026-09-28 10:48:09 +08:00

68 lines
2.9 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.
# 构建 + 运行一体镜像。
#
# 服务契约来源(交叉验证):
# - node_modules/next/dist/docs/01-app/03-api-reference/05-config/01-next-config-js/output.md:
# output: 'standalone' 产出可独立部署的目录 + 精简 server.js;该 server **默认不含** public
# 与 static,需手工拷到 <standalone>/public 与 <standalone>/.next/static(本项目 distDir=dist,
# 实测为 <standalone>/dist/static,见下);监听地址/端口由 HOSTNAME / PORT 环境变量决定。
# - 本仓库 dist/ 实测:dist/standalone/server.js、dist/standalone/dist/{BUILD_ID,server,...}、
# dist/static/{chunks,media,<buildId>}。
#
# 与 Dockerfile.prod 的分工(避免第三种变体):
# - Dockerfile.prod:直接复用**宿主机已构建**的 dist/standalone,宿主为 darwin,
# 因此需要 sharp-deps 阶段补 linux-musl 的 @img 二进制。
# - 本文件:镜像内完成 npm ci + next build(依赖原生装到 linux-musl),无需覆盖 @img。
#
# 历史缺陷(ACCEPTANCE_REVIEW_2026-09-21 §5):旧版把 /app/dist 当静态 HTML 根
# `COPY --from=builder /app/dist /usr/share/nginx/html` 交给 nginx,standalone 产物里没有
# 可直服的站点根目录(HTML 在 dist/standalone/dist/server/app/*.html,且需运行时渲染),
# 用本镜像部署即白屏/404。
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci && npm cache clean --force
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
# 先删除构建上下文里带进来的宿主产物:.dockerignore 为 Dockerfile.prod 放行了
# dist/standalone 与 dist/static,而 next build 不会清空目标目录,残留的
# dist/standalone/node_modules/@img/*-darwin-* 会被下面的 runner 原样拷进 linux 镜像。
RUN rm -rf "${NEXT_DIST_DIR:-dist}" && npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000
# standalone server 只绑 HOSTNAME,默认 localhost 在容器外不可达
ENV HOSTNAME="0.0.0.0"
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
# Next.js 16 standalone 输出:server.js 位于 dist/standalone 根目录(与 Dockerfile.prod 一致)
# 注:以下三个路径按 next.config.mjs 的默认 distDir=dist 硬编码;若 CI 用 NEXT_DIST_DIR 改目录,
# 需同步这里的 --from 路径(当前 Jenkinsfile 未设置该变量)。
COPY --from=builder /app/dist/standalone ./
# 客户端静态资源,standalone 内的 distDir 影子目录为 dist/
COPY --from=builder /app/dist/static ./dist/static
# 公共静态资源(图片、字体、favicon、uploads)
COPY --from=builder /app/public ./public
RUN chown -R nextjs:nodejs /app
USER nextjs
EXPOSE 3000
# 应用层安全响应头由 next.config.mjs 的 headers() 发出,本镜像不再叠加 nginx 层,
# 因此容器直连(无 nginx)时头部依然完整。
CMD ["node", "server.js"]