`next build` on Turbopack never completes on this app. The compiler is a
single native process whose RSS grows monotonically with no plateau:
0.9G -> 1.6G -> 2.8G -> 5.0G -> 5.5G -> 6.2G -> killed
It still dies with 4GB of swap attached, at 12GB RSS. The build workers are
only 0.17GB each, so `experimental.cpus` is not the lever either.
A `--max-old-space-size` cap cannot help: measured with a 2GB cap, RSS still
reached 8GB, because the memory is native Turbopack (Rust) memory rather than
the V8 heap. The cap added in 1c9ddcd4 was therefore inert and only created
false confidence, so it is dropped from the build script.
Webpack builds the same 329 routes in ~95s with a ~6GB peak.
Ruled out by measurement: the 25 bundled locale files (stubbing 24 of them
from 7.1MB down to 276KB still peaked at 11GB), worker count, and the
flatten/unflatten message pipeline (600 iterations cost 6.4s and settle at
39MB of heap).
Verified: `pnpm run build` exits 0, TypeScript passes, 279/279 static pages are
generated, and the standalone output boots and serves /, /login and /register.
67 lines
2.8 KiB
Docker
67 lines
2.8 KiB
Docker
# syntax=docker/dockerfile:1
|
|
FROM node:26.10.0-alpine AS migrations
|
|
WORKDIR /app
|
|
ENV NEXT_TELEMETRY_DISABLED=1
|
|
|
|
# Installeer git en pnpm v12
|
|
RUN --mount=type=cache,target=/var/cache/apk \
|
|
apk add --no-cache git \
|
|
&& npm install -g [email protected]
|
|
|
|
# Stel het PATH zo in dat Alpine pnpm gegarandeerd overal herkent
|
|
ENV PNPM_HOME="/usr/local/share/pnpm"
|
|
ENV PATH="$PNPM_HOME:/usr/local/bin:$PATH"
|
|
|
|
COPY package.json pnpm-lock.yaml* pnpm-workspace.yaml* .npmrc* ./
|
|
|
|
# Voer de installatie uit met de pnpm v12 store cache-mount
|
|
RUN --mount=type=cache,target=/root/.local/share/pnpm/store \
|
|
pnpm install --frozen-lockfile --ignore-scripts
|
|
|
|
COPY . .
|
|
ARG NEXT_DEPLOYMENT_ID="unknown"
|
|
LABEL org.opencontainers.image.revision="$NEXT_DEPLOYMENT_ID"
|
|
|
|
FROM migrations AS builder
|
|
ARG NEXT_DEPLOYMENT_ID="unknown"
|
|
ENV NEXT_DEPLOYMENT_ID="$NEXT_DEPLOYMENT_ID"
|
|
|
|
# The build runs the webpack builder (see the `build` script in package.json).
|
|
# Turbopack's compiler is a single native process that grows past 12GB RSS on
|
|
# this 329-route app and gets OOM-killed; webpack peaks around 5GB. A
|
|
# --max-old-space-size cap does NOT help, because that memory is native
|
|
# Turbopack memory rather than the V8 heap.
|
|
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
|
|
|
# Bouw de Next.js applicatie met caching
|
|
RUN --mount=type=cache,target=/app/.next/cache \
|
|
DATABASE_URL="mysql://build:[email protected]:9/build" \
|
|
HOTEL_NAME="Build fixture" APP_URL="http://localhost:3002" \
|
|
AUTH_SECRET="build-fixture-not-for-runtime-use-000000000000" \
|
|
pnpm run build \
|
|
&& PERFORMANCE_COMMIT_SHA="$NEXT_DEPLOYMENT_ID" node scripts/performance-report.mjs --output-dir build-reports
|
|
|
|
FROM node:26.10.0-alpine AS runner
|
|
ARG NEXT_DEPLOYMENT_ID="unknown"
|
|
LABEL org.opencontainers.image.revision="$NEXT_DEPLOYMENT_ID"
|
|
WORKDIR /app
|
|
ENV NODE_ENV=production \
|
|
NEXT_TELEMETRY_DISABLED=1 \
|
|
PORT=3002 \
|
|
HOSTNAME=0.0.0.0
|
|
RUN apk add --no-cache tini curl \
|
|
&& addgroup -g 33 -S nextjs && adduser -u 33 -S -G nextjs nextjs \
|
|
&& mkdir -p /app/storage /app/public/nitro-assets /app/public/swf /var/www/Gamedata \
|
|
&& chown -R 33:33 /app/storage /app/public /var/www/Gamedata
|
|
COPY --from=builder --chown=nextjs:nextjs /app/public ./public
|
|
COPY --from=builder --chown=nextjs:nextjs /app/.next/standalone ./
|
|
COPY --from=builder --chown=nextjs:nextjs /app/.next/static ./.next/static
|
|
COPY --from=builder --chown=nextjs:nextjs /app/build-reports ./build-reports
|
|
COPY --from=builder --chown=nextjs:nextjs /app/drizzle/migrations ./drizzle/migrations
|
|
COPY --chown=nextjs:nextjs scripts/docker-start.mjs ./docker-start.mjs
|
|
USER nextjs
|
|
EXPOSE 3002
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
|
|
CMD ["node", "-e", "fetch('http://127.0.0.1:'+(process.env.PORT||'3002')+'/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
|
|
ENTRYPOINT ["/sbin/tini", "--"]
|
|
CMD ["node", "docker-start.mjs"] |