Dockerfile
此代码来自构建时的仓库快照。修改源码后重新构建即可更新。
# syntax=docker/dockerfile:1
FROM node:24-bookworm-slim AS runtime
RUN apt-get update && apt-get install -y --no-install-recommends openssl ca-certificates && rm -rf /var/lib/apt/lists/*
FROM runtime AS base
WORKDIR /app
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm install --global pnpm@12.10.1
FROM base AS deps
ENV HUSKY=0
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY prisma ./prisma
COPY prisma.config.ts ./
RUN pnpm install --frozen-lockfile
FROM deps AS build
COPY src ./src
COPY public ./public
COPY scripts ./scripts
COPY tests ./tests
COPY tsconfig.json next.config.ts postcss.config.mjs vitest.config.mts ./
RUN pnpm build
# Web 只复制 Next.js 追踪的运行依赖,构建不接收真实密钥。
FROM runtime AS web
WORKDIR /app
ENV NODE_ENV=production NEXT_TELEMETRY_DISABLED=1 PORT=3000 HOSTNAME=0.0.0.0
COPY --from=build --chown=node:node /app/.next/standalone ./
COPY --from=build --chown=node:node /app/.next/static ./.next/static
COPY --from=build --chown=node:node /app/public ./public
USER node
EXPOSE 3000
HEALTHCHECK --interval=15s --timeout=10s --start-period=20s CMD node -e "fetch('http://127.0.0.1:3000/api/health',{signal:AbortSignal.timeout(8000)}).then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
CMD ["node", "server.js"]
FROM base AS worker-deps
ENV HUSKY=0
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
RUN pnpm install --prod --frozen-lockfile --ignore-scripts
FROM base AS worker
ENV NODE_ENV=production
COPY --from=worker-deps --chown=node:node /app/node_modules ./node_modules
COPY --from=build --chown=node:node /app/src ./src
COPY --from=build --chown=node:node /app/scripts ./scripts
COPY --from=build --chown=node:node /app/tsconfig.json /app/package.json ./
USER node
HEALTHCHECK --interval=15s --timeout=6s --start-period=20s CMD ["node", "--import", "tsx", "scripts/worker-health.ts"]
CMD ["node", "--import", "tsx", "src/worker/index.ts"]
# 迁移单独执行一次;不让 Web 和多个 Worker 并发修改表结构。
FROM deps AS migrate
ENV NODE_ENV=production
USER node
CMD ["./node_modules/.bin/prisma", "migrate", "deploy"]