# build stage — install the whole workspace so @dbmole/core resolves, build esmole FROM node:22-alpine AS build WORKDIR /repo COPY package.json package-lock.json tsconfig.base.json ./ COPY packages/core/package.json packages/core/ COPY packages/dbmole-mcp/package.json packages/dbmole-mcp/ COPY packages/esmole-mcp/package.json packages/esmole-mcp/ RUN npm ci COPY packages/core packages/core COPY packages/esmole-mcp packages/esmole-mcp # tsup bundles @dbmole/core into dist (noExternal); the remaining runtime deps # (undici, MCP SDK, zod, ssh2) stay external and are served from node_modules. RUN npm run build --workspace esmole-mcp && npm prune --omit=dev # runtime stage — dist (core bundled in) + pruned production node_modules FROM node:22-alpine AS runtime WORKDIR /app ENV NODE_ENV=production # Root hoists most prod deps (MCP SDK, zod, ssh2); npm nests a few per-package # (undici). Copy both so every external the bundle requires resolves under # /app/node_modules at runtime. COPY --from=build /repo/node_modules ./node_modules COPY --from=build /repo/packages/esmole-mcp/node_modules ./node_modules COPY --from=build /repo/packages/esmole-mcp/dist ./dist RUN mkdir -p /home/node/.config/esmole && chown -R node:node /home/node/.config USER node ENTRYPOINT ["node", "dist/index.js"]