From 520c12117654879b8b9ff7e2e6c4636507c71a1e Mon Sep 17 00:00:00 2001 From: gitea-robot Date: Fri, 31 Jul 2026 20:15:15 +0800 Subject: [PATCH] docs: Node Dockerfile hard rules (NODE_ENV, heap, serialize stages) --- dokploy-gitea-deploy/SKILL.md | 6 ++ .../references/stack-profiles.md | 77 +++++++++++++++---- 2 files changed, 68 insertions(+), 15 deletions(-) diff --git a/dokploy-gitea-deploy/SKILL.md b/dokploy-gitea-deploy/SKILL.md index 5c6ef88..c0b794e 100644 --- a/dokploy-gitea-deploy/SKILL.md +++ b/dokploy-gitea-deploy/SKILL.md @@ -123,6 +123,10 @@ MCP endpoint:`https://company-deploy-mcp.loncode.site/mcp` - 识别栈;保证 Dockerfile;`.gitignore` 排除密钥 - 有状态:默认 `/data`;多目录用 `persistence[]` - 需要库:`databases: [{ engine: "postgres"|"mysql", ... }]` +- **Node 多阶段硬规则**(详见 `stack-profiles.md`): + - 禁止在 `npm ci`/`pnpm install` **之前** `ENV NODE_ENV=production`(否则 `nest`/`vite` not found) + - 大前端 Vite:`NODE_OPTIONS=--max-old-space-size=3072` + - runtime 用 `COPY --from=build` 串行,避免并行双 `npm ci` 把小机打爆 ### 2. 仓库与推送(权限红线) @@ -299,6 +303,8 @@ Agent **不要**在 MCP 路径下再调 Dokploy `domain.create`(避免双绑/ |------|------| | 401 / 要 Feishu Key | 引导连接中心登录,配置 `buxi_` | | git push 权限 / Permission denied / 要配 SSH | **错误路径**。改用 `ensure_repository` → `agentHint.pushUrl` 推送;禁止给用户配 SSH | +| `nest: not found` / `vite: not found` | build 阶段在装依赖前设了 `NODE_ENV=production`;先全量 `npm ci` 再设 production | +| `JavaScript heap out of memory` | Dockerfile build 加 `NODE_OPTIONS=--max-old-space-size=3072`;避免并行 npm ci;机器内存过小则升配 | | 运行中项目达上限 | `get_my_quota`;停/删旧应用后再部署 | | Forbidden 看他人项目 | 非管理员;加 `ADMIN_OPEN_IDS` 或只查自己的 | | 有部署无 HTTPS | 等 LE;查 DNS/80;控制面证书配置 | diff --git a/dokploy-gitea-deploy/references/stack-profiles.md b/dokploy-gitea-deploy/references/stack-profiles.md index b571c10..c0be005 100644 --- a/dokploy-gitea-deploy/references/stack-profiles.md +++ b/dokploy-gitea-deploy/references/stack-profiles.md @@ -113,43 +113,90 @@ CMD ["uv", "run", "your-entrypoint"] 检测:`package.json`,优先 `pnpm-lock.yaml` → `package-lock.json` → `yarn.lock`。 -推荐结构(standalone / 需 `node` 运行): +### Dockerfile 硬规则(踩过的坑,Agent 必守) + +| 错误 | 现象 | 正确做法 | +|------|------|----------| +| 在 **build 阶段 `npm ci` 之前** `ENV NODE_ENV=production` | `nest: not found` / `vite: not found`;日志里 packages 只有几百个(缺 devDependencies) | **先** `npm ci`(装全量含 dev)→ **再** `ENV NODE_ENV=production` → `npm run build` | +| 不设 Node 堆、大前端 Vite 打包 | `FATAL ERROR: JavaScript heap out of memory` | build 阶段:`ENV NODE_OPTIONS=--max-old-space-size=3072`(小机 3~4G 可试 2560) | +| multi-stage 里 **build 与 runtime 无依赖** | Docker **并行** 两个 `npm ci`,小机内存翻倍易 OOM | runtime 至少 `COPY --from=build …` 一件产物,让 build 先完成 | +| 用用户 SSH 推 Gitea | Permission denied | 用 `ensure_repository` 的 `pushUrl`,见 SKILL | + +### 推荐:Nest + Vite 全栈模板 ```dockerfile -FROM node:22-bookworm-slim AS deps -WORKDIR /app -RUN corepack enable -COPY package.json pnpm-lock.yaml ./ -# 可选:COPY .npmrc ./ -RUN --mount=type=cache,target=/root/.local/share/pnpm/store \ - pnpm install --frozen-lockfile - FROM node:22-bookworm-slim AS build WORKDIR /app +# ① 提高堆;② 此时不要 NODE_ENV=production +ENV NODE_OPTIONS=--max-old-space-size=3072 + +COPY package.json package-lock.json ./ +RUN npm ci --ignore-scripts + +COPY . ./ +# ③ 仅编译时 production +ENV NODE_ENV=production +RUN npm run build:prod && npm cache clean --force + +FROM node:22-bookworm-slim AS runtime +WORKDIR /app +ENV NODE_ENV=production \ + SERVER_HOST=0.0.0.0 \ + SERVER_PORT=3000 \ + DATA_DIR=/data + +COPY package.json package-lock.json ./ +# ④ 依赖 build,避免与 vite 并行 npm ci +COPY --from=build /app/package.json /tmp/.build-done +RUN npm ci --omit=dev --ignore-scripts && npm cache clean --force +COPY --from=build /app/dist ./ + +EXPOSE 3000 +CMD ["node", "server/main.js"] +``` + +### 推荐:较轻的 Node API(pnpm) + +```dockerfile +FROM node:22-bookworm-slim AS build +WORKDIR /app +ENV NODE_OPTIONS=--max-old-space-size=2048 RUN corepack enable -COPY --from=deps /app/node_modules ./node_modules +COPY package.json pnpm-lock.yaml ./ +RUN --mount=type=cache,target=/root/.local/share/pnpm/store \ + pnpm install --frozen-lockfile COPY . . +ENV NODE_ENV=production RUN pnpm run build FROM node:22-bookworm-slim AS runner WORKDIR /app -ENV NODE_ENV=production -ENV DATA_DIR=/data +ENV NODE_ENV=production DATA_DIR=/data COPY --from=build /app/dist ./dist COPY --from=build /app/package.json ./ -COPY --from=deps /app/node_modules ./node_modules +COPY --from=build /app/node_modules ./node_modules +# 若 node_modules 含 dev,可改为 runner 单独 pnpm install --prod EXPOSE 3000 CMD ["node", "dist/index.js"] ``` -静态前端(Vite 等)可用 `nginx:stable-alpine` 拷 `dist`;`spec.port` 多为 `80`。 +静态前端(Vite 等)可用 `nginx:stable-alpine` 拷 `dist`;`spec.port` 多为 `80`。 +纯静态站构建同样需要 **devDependencies**(vite)在 build 阶段装全。 -Registry 加速示例 `.npmrc`(可提交或构建时注入): +Registry 加速示例 `.npmrc`: ```ini registry=https://registry.npmmirror.com ``` +### 部署前 Agent 自检(Node) + +- [ ] Dockerfile **没有**在安装依赖前设置 `NODE_ENV=production` +- [ ] `nest` / `vite` / `tsc` 等 CLI 在 **devDependencies** 且 build 阶段能装到 +- [ ] 大前端:`NODE_OPTIONS=--max-old-space-size=3072`(或更高,视机器) +- [ ] multi-stage:runtime 依赖 build,避免并行双 `npm ci` +- [ ] 运行 `CMD` 只跑编译产物,**不**在 runtime 再 `nest build` + --- ## Docker Compose