From 985627b2c96335b7bfc8b2ce320e0c3655f75ff9 Mon Sep 17 00:00:00 2001 From: opspawn Date: Fri, 20 Feb 2026 17:46:36 +0000 Subject: [PATCH 1/9] fix(ui): replace bun with npm in Dockerfile to fix SIGILL crash (#1331) Bun crashes with SIGILL (illegal instruction) during Next.js build in Docker CI. Replace bun with npm/node across the UI Docker build: - Use wolfi apk nodejs/npm packages instead of bun install script - Use npm ci for dependency installation (frozen lockfile) - Use npm run build instead of bun run build - Use node to run server.js in supervisord (runtime stage) - Update ui/Makefile to use npm commands for local dev - Remove TOOLS_BUN_VERSION ARG and bun-related ENV vars Signed-off-by: opspawn Signed-off-by: fl-sean03 --- ui/Dockerfile | 43 +++++++++++----------------------------- ui/Makefile | 20 +++++-------------- ui/conf/supervisord.conf | 4 ++-- 3 files changed, 19 insertions(+), 48 deletions(-) diff --git a/ui/Dockerfile b/ui/Dockerfile index 4e04c2251..572eb138b 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -10,35 +10,24 @@ ARG BUILDPLATFORM RUN --mount=type=cache,target=/var/cache/apk,rw \ echo "Installing on $BUILDPLATFORM" \ && apk update \ - && apk add curl bash openssl unzip ca-certificates nginx supervisor \ - && update-ca-certificates + && apk add curl bash openssl unzip ca-certificates nginx supervisor nodejs npm \ + && update-ca-certificates \ + && node --version \ + && npm --version -ARG TOOLS_BUN_VERSION ARG TARGETARCH ENV DO_NOT_TRACK=1 ENV NEXT_TELEMETRY_DISABLED=1 -ENV BUN_INSTALL_CACHE_DIR=/cache/bun -ENV BUN_INSTALL=/usr/local/bun ENV NODE_ENV=production ENV CYPRESS_INSTALL_BINARY=0 -ENV PATH=$BUN_INSTALL/bin:$PATH - -# Install Bun (uses official install script) -# brew install oven-sh/bun/bun -RUN --mount=type=cache,target=/cache/bun,rw \ - mkdir -p $BUN_INSTALL \ - && curl -fsSL https://bun.sh/install | bash -s "bun-v$TOOLS_BUN_VERSION" \ - && bun --version WORKDIR /app/ui # Copy package files and install dependencies COPY package*.json ./ RUN --mount=type=cache,target=/cache/node_modules,rw \ - bun install --frozen-lockfile \ - && bun pm ls --all \ - && bun pm hash + npm ci ### STAGE 2: Build FROM --platform=$BUILDPLATFORM deps AS builder @@ -46,12 +35,12 @@ FROM --platform=$BUILDPLATFORM deps AS builder # Copy source files COPY . . -# Build the application (native compilation for speed) +# Build the application RUN --mount=type=cache,target=/cache/node_modules,rw \ --mount=type=cache,target=/app/ui/.next/cache,rw \ export NEXT_TELEMETRY_DEBUG=1 \ - && bun install --frozen-lockfile \ - && bun run build \ + && npm ci \ + && npm run build \ && mkdir -p /app/ui/public ### STAGE 3: Runtime @@ -64,17 +53,9 @@ ARG BUILDPLATFORM RUN --mount=type=cache,target=/var/cache/apk,rw \ echo "Installing on $BUILDPLATFORM" \ && apk update \ - && apk add curl bash openssl unzip ca-certificates nginx supervisor \ - && update-ca-certificates - -ARG TOOLS_BUN_VERSION -ENV BUN_INSTALL=/usr/local/bun -ENV PATH=$BUN_INSTALL/bin:$PATH -# Install Bun in native arch for running (uses official install script) -# brew install oven-sh/bun/bun -RUN mkdir -p $BUN_INSTALL \ - && curl -fsSL https://bun.sh/install | bash -s "bun-v$TOOLS_BUN_VERSION" \ - && bun --version + && apk add curl bash openssl unzip ca-certificates nginx supervisor nodejs \ + && update-ca-certificates \ + && node --version RUN mkdir -p /app/ui/public /tmp/nginx/client_temp /tmp/nginx/proxy_temp /tmp/nginx/fastcgi_temp /tmp/nginx/uwsgi_temp /tmp/nginx/scgi_temp \ && addgroup -g 1001 nginx \ @@ -108,4 +89,4 @@ LABEL org.opencontainers.image.version="$VERSION" USER nextjs -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] \ No newline at end of file +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] diff --git a/ui/Makefile b/ui/Makefile index 5e0a1b261..cd87494e9 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -1,34 +1,24 @@ -# Install bun -# https://bun.sh/docs/installation - .PHONY: build build: - rm -f bun.lockb - bun install - bun run build + npm install + npm run build .PHONY: clean clean: rm -rf node_modules - rm -f bun.lockb rm -rf dist - rm -rf .bun rm -rf .cache -.PHONY: install-bun -install-bun: - brew install bun - .PHONY: audit audit: @echo "Running security audit..." - bun audit + npm audit @echo "Security audit completed." .PHONY: build update: @echo "Updating UI lock file..." npm audit fix - bun install --frozen-lockfile --production - @echo "Updating UI lock file done." \ No newline at end of file + npm install --production + @echo "Updating UI lock file done." diff --git a/ui/conf/supervisord.conf b/ui/conf/supervisord.conf index 495f24524..a0d6b36ba 100644 --- a/ui/conf/supervisord.conf +++ b/ui/conf/supervisord.conf @@ -20,9 +20,9 @@ stdout_events_enabled=true stderr_events_enabled=true [program:nextjs] -command=bun /app/ui/server.js +command=node /app/ui/server.js directory=/app/ui -environment=PORT=8001,HOSTNAME="0.0.0.0",NODE_ENV=production,PATH="/usr/local/bun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" +environment=PORT=8001,HOSTNAME="0.0.0.0",NODE_ENV=production autostart=true autorestart=true startretries=5 From 2730aec89751b840094d2ad1387f02e91988eb3c Mon Sep 17 00:00:00 2001 From: opspawn Date: Fri, 20 Feb 2026 19:36:05 +0000 Subject: [PATCH 2/9] fix(ui): use nodejs-22 package name for Wolfi base image Wolfi (cgr.dev/chainguard/wolfi-base) uses versioned package names for Node.js (e.g. nodejs-22) rather than a generic 'nodejs' package. The previous 'apk add nodejs' failed with package-not-found on CI. Signed-off-by: opspawn Signed-off-by: fl-sean03 --- ui/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/Dockerfile b/ui/Dockerfile index 572eb138b..df01913ce 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -10,7 +10,7 @@ ARG BUILDPLATFORM RUN --mount=type=cache,target=/var/cache/apk,rw \ echo "Installing on $BUILDPLATFORM" \ && apk update \ - && apk add curl bash openssl unzip ca-certificates nginx supervisor nodejs npm \ + && apk add curl bash openssl unzip ca-certificates nginx supervisor nodejs-22 npm \ && update-ca-certificates \ && node --version \ && npm --version @@ -53,7 +53,7 @@ ARG BUILDPLATFORM RUN --mount=type=cache,target=/var/cache/apk,rw \ echo "Installing on $BUILDPLATFORM" \ && apk update \ - && apk add curl bash openssl unzip ca-certificates nginx supervisor nodejs \ + && apk add curl bash openssl unzip ca-certificates nginx supervisor nodejs-22 \ && update-ca-certificates \ && node --version From 8ee8f5e7028d7f8065fca90eb047bb1f8bfe5dcb Mon Sep 17 00:00:00 2001 From: opspawn Date: Fri, 20 Feb 2026 19:45:24 +0000 Subject: [PATCH 3/9] fix(ui): clear stale APK index cache before apk update The BuildKit cache mount at /var/cache/apk retains stale APKINDEX files from previous CI runs that didn't include nodejs-22/npm. This causes 'apk update' to fail with 'No such file or directory' when the cached index can't resolve the new packages. Remove stale index files before update to force a fresh download. Signed-off-by: opspawn Signed-off-by: fl-sean03 --- ui/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/Dockerfile b/ui/Dockerfile index df01913ce..4c2c358b9 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -9,6 +9,7 @@ ARG BUILDPLATFORM RUN --mount=type=cache,target=/var/cache/apk,rw \ echo "Installing on $BUILDPLATFORM" \ + && rm -f /var/cache/apk/APKINDEX.*.tar.gz \ && apk update \ && apk add curl bash openssl unzip ca-certificates nginx supervisor nodejs-22 npm \ && update-ca-certificates \ @@ -52,6 +53,7 @@ ARG BUILDPLATFORM RUN --mount=type=cache,target=/var/cache/apk,rw \ echo "Installing on $BUILDPLATFORM" \ + && rm -f /var/cache/apk/APKINDEX.*.tar.gz \ && apk update \ && apk add curl bash openssl unzip ca-certificates nginx supervisor nodejs-22 \ && update-ca-certificates \ From 3e34340a4aea8ef070685005116f7c49c7218de9 Mon Sep 17 00:00:00 2001 From: opspawn Date: Fri, 20 Feb 2026 20:12:43 +0000 Subject: [PATCH 4/9] fix(ui): resolve apk cache contention in multi-stage Docker build Remove rm -f of APKINDEX files that caused stale cache errors in CI buildx. Use separate cache id for final stage to avoid contention with deps stage during parallel builds. Signed-off-by: opspawn Signed-off-by: opspawn Signed-off-by: fl-sean03 --- ui/Dockerfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/Dockerfile b/ui/Dockerfile index 4c2c358b9..74797ee1d 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -9,7 +9,6 @@ ARG BUILDPLATFORM RUN --mount=type=cache,target=/var/cache/apk,rw \ echo "Installing on $BUILDPLATFORM" \ - && rm -f /var/cache/apk/APKINDEX.*.tar.gz \ && apk update \ && apk add curl bash openssl unzip ca-certificates nginx supervisor nodejs-22 npm \ && update-ca-certificates \ @@ -51,9 +50,8 @@ ENV LC_ALL=C.UTF-8 # This is used to print the build platform in the logs ARG BUILDPLATFORM -RUN --mount=type=cache,target=/var/cache/apk,rw \ +RUN --mount=type=cache,id=apk-final,target=/var/cache/apk,rw \ echo "Installing on $BUILDPLATFORM" \ - && rm -f /var/cache/apk/APKINDEX.*.tar.gz \ && apk update \ && apk add curl bash openssl unzip ca-certificates nginx supervisor nodejs-22 \ && update-ca-certificates \ From c2996d84d4697a89d7c36a5ccf57104b26a06aad Mon Sep 17 00:00:00 2001 From: opspawn Date: Fri, 20 Feb 2026 21:56:31 +0000 Subject: [PATCH 5/9] fix(ui): address Copilot review comments on Dockerfile and Makefile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move NODE_ENV=production from deps stage to runtime stage so devDependencies are available during `npm ci` / `next build` - Remove redundant `npm ci` from deps stage (builder inherits from deps and already runs `npm ci`) - Change BuildKit cache mount from /cache/node_modules to /root/.npm (npm cache directory) - Fix Makefile .PHONY declaration: build → update for the update target - Change Makefile update target from `npm install --production` to `npm ci` Signed-off-by: opspawn Signed-off-by: fl-sean03 --- ui/Dockerfile | 13 +++++-------- ui/Makefile | 4 ++-- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/ui/Dockerfile b/ui/Dockerfile index 74797ee1d..525aafd40 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -19,15 +19,12 @@ ARG TARGETARCH ENV DO_NOT_TRACK=1 ENV NEXT_TELEMETRY_DISABLED=1 -ENV NODE_ENV=production ENV CYPRESS_INSTALL_BINARY=0 WORKDIR /app/ui -# Copy package files and install dependencies +# Copy package files for layer caching COPY package*.json ./ -RUN --mount=type=cache,target=/cache/node_modules,rw \ - npm ci ### STAGE 2: Build FROM --platform=$BUILDPLATFORM deps AS builder @@ -35,11 +32,10 @@ FROM --platform=$BUILDPLATFORM deps AS builder # Copy source files COPY . . -# Build the application -RUN --mount=type=cache,target=/cache/node_modules,rw \ +# Install all dependencies (including devDependencies for next build) and build +RUN --mount=type=cache,target=/root/.npm,rw \ --mount=type=cache,target=/app/ui/.next/cache,rw \ - export NEXT_TELEMETRY_DEBUG=1 \ - && npm ci \ + npm ci \ && npm run build \ && mkdir -p /app/ui/public @@ -47,6 +43,7 @@ RUN --mount=type=cache,target=/cache/node_modules,rw \ FROM $BASE_IMAGE_REGISTRY/chainguard/wolfi-base:latest AS final ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 +ENV NODE_ENV=production # This is used to print the build platform in the logs ARG BUILDPLATFORM diff --git a/ui/Makefile b/ui/Makefile index cd87494e9..92e95068e 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -16,9 +16,9 @@ audit: npm audit @echo "Security audit completed." -.PHONY: build +.PHONY: update update: @echo "Updating UI lock file..." npm audit fix - npm install --production + npm ci @echo "Updating UI lock file done." From 2f1b8c08e2677a366acdc736f2572b95b6512ea1 Mon Sep 17 00:00:00 2001 From: opspawn Date: Fri, 20 Feb 2026 22:21:41 +0000 Subject: [PATCH 6/9] fix(ui): use npm ci instead of npm install in Makefile build target npm ci ensures reproducible builds from the lockfile, matching the Docker build stage and CI pipeline behavior. Signed-off-by: opspawn Signed-off-by: fl-sean03 --- ui/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/Makefile b/ui/Makefile index 92e95068e..096c81533 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -1,7 +1,7 @@ .PHONY: build build: - npm install + npm ci npm run build .PHONY: clean From 025f2e36f75b701c1c311cedb7c4f8c5b9174c27 Mon Sep 17 00:00:00 2001 From: opspawn Date: Fri, 20 Feb 2026 23:17:34 +0000 Subject: [PATCH 7/9] ci: retrigger CI (e2e flake: MCP session cancel scope race) Signed-off-by: opspawn Signed-off-by: fl-sean03 From 1a0fc42ad3ba29703db8f949840ee2b9503f9a78 Mon Sep 17 00:00:00 2001 From: fl-sean03 Date: Fri, 27 Feb 2026 05:48:17 +0000 Subject: [PATCH 8/9] docs: explain rationale for npm over bun in Dockerfile Addresses reviewer question about why we switched from bun to node/npm: 1. Bun SIGILL crash (#1331): Bun emits illegal CPU instructions during Next.js builds on certain Docker platforms (wolfi-base + multi-arch). This is a known bun issue with no upstream fix available. 2. Bun upgrade insufficient: PR #1330 tried upgrading bun versions but the SIGILL persisted across versions, ruling out a version-specific bug. 3. CI alignment: The ui-tests CI job already uses npm for testing. Having the Docker build also use npm eliminates the bun/npm divergence and ensures build parity between CI and container image. 4. No functionality loss: Next.js standalone output (produced by `next build`) is runtime-agnostic. `node server.js` and `bun server.js` produce identical behavior for serving the standalone output. Signed-off-by: opspawn Signed-off-by: fl-sean03 --- ui/Dockerfile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ui/Dockerfile b/ui/Dockerfile index 525aafd40..85b5e94f7 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -1,3 +1,9 @@ +# Uses Node.js + npm instead of Bun because: +# - Bun crashes with SIGILL on certain Docker build platforms (see #1331) +# - Upgrading Bun versions (#1330) did not resolve the SIGILL issue +# - The CI ui-tests job already uses npm, so this aligns Docker with CI +# - Node.js standalone output (next build) works identically with node runtime + ### STAGE 1: Dependencies and Build ARG BASE_IMAGE_REGISTRY=cgr.dev ARG BUILDPLATFORM From e0791460ada8746e05a92a2309074bd50ac43cdc Mon Sep 17 00:00:00 2001 From: fl-sean03 Date: Fri, 27 Feb 2026 10:49:35 +0000 Subject: [PATCH 9/9] docs: add upstream bun issue reference to Dockerfile comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re: EItanya's review — "Why is switching away from bun to node the approach you decided on?" Updated the Dockerfile comment to include the upstream bun issue URL (oven-sh/bun#4890) which documents the SIGILL crash when bun runs under Docker with qemu cross-compilation. The root cause is that bun's JIT compiler and native code emits CPU instructions (e.g., AVX2) that are not available under qemu user-mode emulation. This affects all bun versions, not just the one originally used — which is why the bun upgrade attempt in #1330 did not help. npm was chosen because: 1. It avoids the SIGILL crash entirely (Node.js does not use qemu- incompatible JIT in the same way) 2. The CI ui-tests job already uses npm, so Docker now matches CI 3. Next.js standalone output is runtime-agnostic — node server.js and bun server.js produce identical behavior Signed-off-by: opspawn Signed-off-by: fl-sean03 --- ui/Dockerfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/Dockerfile b/ui/Dockerfile index 85b5e94f7..29482d127 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -1,8 +1,8 @@ -# Uses Node.js + npm instead of Bun because: -# - Bun crashes with SIGILL on certain Docker build platforms (see #1331) -# - Upgrading Bun versions (#1330) did not resolve the SIGILL issue -# - The CI ui-tests job already uses npm, so this aligns Docker with CI -# - Node.js standalone output (next build) works identically with node runtime +# Using npm instead of bun due to SIGILL crashes when building under Docker +# with qemu cross-compilation (known bun issue: https://github.com/oven-sh/bun/issues/4890). +# This was the root cause of kagent-dev/kagent#1331. +# Upgrading bun (#1330) did not resolve the crash — it affects all bun versions on qemu. +# npm aligns the Docker build with CI (ui-tests already uses npm). ### STAGE 1: Dependencies and Build ARG BASE_IMAGE_REGISTRY=cgr.dev