FROM node:24.21.0-alpine AS base FROM base AS builder RUN npm install -g pnpm@11.1.3 WORKDIR /app # the vite client build exceeds node's default ~2GB heap ENV NODE_OPTIONS="--max-old-space-size=4096" # dependencies come from the manifests alone, so this layer survives every # change that does not touch them — which is what makes a rebuild after an # ordinary source edit cheap. Scripts are skipped here because the root # `prepare` runs `nuxt prepare`, which has no sources at this point. COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ RUN pnpm install --frozen-lockfile --ignore-scripts COPY . . # the dependency tree is already in place, so this install only runs the # scripts skipped above (`prepare`, and the allowBuilds native packages). # The node-server preset produces a self-contained SSR server in .output # that reads NUXT_PUBLIC_* / NUXT_* runtime config from env at startup. RUN pnpm install --frozen-lockfile && \ NITRO_PRESET=node-server pnpm run build:web FROM base AS runner WORKDIR /app RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nuxt COPY --from=builder --chown=nuxt:nodejs /app/.output /app/.output ENV NODE_ENV=production USER nuxt EXPOSE 3000 CMD ["node", "/app/.output/server/index.mjs"]