docker: bump web build heap to 2.5GB and serialize behind collab/mcp

The 1.5GB heap cap was actually too aggressive for the Next 15 webpack
compile on this monorepo: V8 spirals into GC churn near the cap, runs
the host out of free memory, and oom-killer SIGKILLs the build (exit 255).

With 4GB on the host now:
  - Cap V8 heap at 2.5GB (~70% of host RAM) — gives the compile real
    headroom while leaving room for kernel + dockerd + concurrent COPY
    layers from the collab/mcp runtime stages.
  - Add depends_on so the lighter collab + mcp services finish building
    before the web target starts its peak-memory compile, instead of
    fighting it for memory in parallel.

Made-with: Cursor
This commit is contained in:
Randall Stillwell 2026-04-27 15:49:41 -05:00
parent 70c9bbf1e5
commit 403437dafc
2 changed files with 15 additions and 6 deletions

View file

@ -51,9 +51,11 @@ COPY docker/next.config.docker.ts ./apps/web/next.config.ts
ENV NEXT_TELEMETRY_DISABLED=1 ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production ENV NODE_ENV=production
# Cap V8 heap so we get a clean JS OOM instead of a kernel SIGKILL (exit 255) # Give the Next.js webpack compile enough V8 heap headroom on the Coolify host.
# if memory pressure spikes during the build on small hosts. # Sized to ~70% of the 4 GB host RAM so kernel + dockerd + concurrent runtime
ENV NODE_OPTIONS=--max-old-space-size=1536 # COPYs from collab/mcp still have breathing room. Below ~2 GB, the compile
# spirals into GC churn and gets oom-killed (exit 255 with no Docker error).
ENV NODE_OPTIONS=--max-old-space-size=2560
RUN pnpm exec turbo build --filter=@tasks/web RUN pnpm exec turbo build --filter=@tasks/web

View file

@ -19,9 +19,13 @@
# #
# Build strategy: # Build strategy:
# All three services share docker/Dockerfile and select runtime via `target:`. # All three services share docker/Dockerfile and select runtime via `target:`.
# The shared `deps` stage (pnpm install for the whole workspace) is hashed # The shared `deps` stage is hashed identically across targets, so BuildKit
# identically across targets, so BuildKit runs it ONCE even when web/collab/mcp # runs `pnpm install` ONCE.
# build in parallel — keeps build-host RAM bounded. #
# `web` declares depends_on collab+mcp so Compose builds the lightweight
# services first and the heavy `next build` (peak ~2.5 GB heap) gets the host
# effectively to itself instead of fighting concurrent runtime-stage COPYs
# for memory.
services: services:
web: web:
@ -29,6 +33,9 @@ services:
context: . context: .
dockerfile: docker/Dockerfile dockerfile: docker/Dockerfile
target: web target: web
depends_on:
- collab
- mcp
restart: unless-stopped restart: unless-stopped
environment: environment:
# Coolify FQDN magic var — set the domain in the Coolify UI for this service. # Coolify FQDN magic var — set the domain in the Coolify UI for this service.