From 6cbb1f64d0194be4f4b322a3c0ee9fe329362642 Mon Sep 17 00:00:00 2001 From: Till JS Date: Thu, 9 Apr 2026 14:10:59 +0200 Subject: [PATCH] fix(api/Dockerfile): switch builder stage to node:20-alpine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit oven/bun:1 doesn't ship with npm or pnpm, so the previous `RUN npm install -g pnpm@9.15.0` failed with `/bin/sh: 1: npm: not found` on the first Mac Mini build. Bun's own install command doesn't honor pnpm-workspace.yaml, so we can't use it as a drop-in. Switch the builder stage to node:20-alpine which has npm built in, install pnpm there, resolve the workspace graph, then COPY the finished tree into the bun runtime stage. The runtime stage stays on oven/bun:1 — bun handles pnpm's node_modules/.pnpm symlink farm natively, so the workspace layout works the same as it does on a developer machine. Tested locally: `docker compose -f docker-compose.macmini.yml build mana-api` now succeeds through the install stage. The runtime stage is unchanged. Co-Authored-By: Claude Opus 4.6 (1M context) --- apps/api/Dockerfile | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/apps/api/Dockerfile b/apps/api/Dockerfile index cae8800a6..828e3bf42 100644 --- a/apps/api/Dockerfile +++ b/apps/api/Dockerfile @@ -2,18 +2,25 @@ # # apps/api — unified Hono/Bun API server # -# Multi-stage build that runs from the monorepo root so the workspace -# packages (@mana/shared-hono, @mana/shared-storage, @mana/media-client, -# @mana/shared-logger) resolve via pnpm before being copied into a -# minimal runtime image. +# Multi-stage build: +# - builder: node:20-alpine with pnpm to resolve the workspace +# dependency graph (@mana/shared-hono + 3 more workspace packages). +# Bun's install command doesn't read pnpm-workspace.yaml, so we use +# pnpm here even though the runtime is Bun. +# - runtime: oven/bun:1 to actually run the server. Bun handles the +# pnpm symlink farm at node_modules/.pnpm/* natively, so the only +# thing the runtime stage needs is the workspace tree the builder +# produced and the entry script. # # Build context MUST be the monorepo root, not apps/api/. The compose # service uses `context: .` for this reason. -FROM oven/bun:1 AS builder +FROM node:20-alpine AS builder WORKDIR /app +RUN npm install -g pnpm@9.15.0 + # Copy the workspace manifest first so the dependency graph is known # before we add source. This caches the install layer for incremental # rebuilds when only source changes. @@ -29,8 +36,8 @@ COPY packages/shared-storage ./packages/shared-storage # @mana/media-client lives under services/mana-media (sub-package). COPY services/mana-media/packages/client ./services/mana-media/packages/client -# Install pnpm and resolve the dependency graph for apps/api. -RUN npm install -g pnpm@9.15.0 +# Resolve the dependency graph for apps/api only (--filter ... +# follows the workspace transitive deps automatically). RUN pnpm install --filter @mana/api... --no-frozen-lockfile --ignore-scripts # Copy the api source and tsconfig last so source-only changes don't