From d4e4f9dbf0d9289c1759503bb310f3d3afa80ff9 Mon Sep 17 00:00:00 2001 From: Randall Stillwell Date: Fri, 5 Jun 2026 21:02:39 -0500 Subject: [PATCH] fix(docker): serialize build stages so next build doesn't OOM on the 8 GB host MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Coolify deploys were failing with exit 255 (kernel OOM, no Docker error) around the 73s mark of `next build`. Root cause: docker/Dockerfile's three build stages (web-build, collab-build, mcp-build) all `FROM deps`, and BuildKit was running them in parallel. The web-build alone wants ~3 GB heap (capped at 5120 MB) and was racing tsup workers + buildkit + dockerd on an 8 GB host until the kernel reaped it. docker-compose.coolify.yml already had a comment claiming `depends_on: [collab, mcp]` on `web` would serialize the builds. It doesn't — `depends_on` only orders runtime startup, not `docker compose build`. Fix: enforce ordering inside the Dockerfile DAG by COPYing one trivial artifact from each lighter stage into web-build. BuildKit now waits for collab-build and mcp-build to finish before starting the heavy Next.js compile, which then gets the host effectively to itself. The copied files land in /tmp and are never read by the runtime web image. Also updated the compose comment to reflect the new (and accurate) ordering mechanism. Co-authored-by: Cursor --- docker/Dockerfile | 10 ++++++++++ docker/docker-compose.coolify.yml | 13 +++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 1c36aa3..0f0d0df 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -49,6 +49,16 @@ COPY packages/database ./packages/database COPY packages/shared ./packages/shared COPY docker/next.config.docker.ts ./apps/web/next.config.ts +# Force BuildKit to finish the two tsup builds before starting the heavy +# Next.js compile. docker-compose's `depends_on` only orders runtime startup, +# not `docker compose build` — without these COPYs, BuildKit runs all three +# build stages in parallel and the host OOMs around the 73s mark of the web +# build (kernel reaps with exit 255 and no Docker error, matching the warning +# below about heap sizing). The copied files are throwaway markers; the +# runtime web image never reads /tmp. +COPY --from=collab-build /app/apps/collab-server/dist/index.mjs /tmp/.collab-built +COPY --from=mcp-build /app/apps/mcp-server/dist/index.js /tmp/.mcp-built + ENV NEXT_TELEMETRY_DISABLED=1 ENV NODE_ENV=production # Give the Next.js webpack compile enough V8 heap headroom on the Coolify host. diff --git a/docker/docker-compose.coolify.yml b/docker/docker-compose.coolify.yml index 15f3d8a..3f1b0d5 100644 --- a/docker/docker-compose.coolify.yml +++ b/docker/docker-compose.coolify.yml @@ -22,10 +22,15 @@ # The shared `deps` stage is hashed identically across targets, so BuildKit # runs `pnpm install` ONCE. # -# `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. +# The heavy `next build` for `web` (peak ~3 GB heap with 5 GB headroom) +# must not race the two tsup builds for collab+mcp on the 8 GB Coolify +# host or the kernel OOM-kills it (exit 255 with no Docker error). Build +# ordering is enforced inside docker/Dockerfile: the `web-build` stage +# has explicit `COPY --from=collab-build` / `COPY --from=mcp-build` lines +# that force BuildKit's DAG to finish those two before starting the web +# compile. The `depends_on` below only orders runtime startup, NOT image +# builds — that was a misconception from an earlier iteration of this +# file. services: web: -- 2.45.2