multica/src/gateway/Dockerfile
yushen 5ba8c87744 fix(gateway): use esbuild to bundle workspace packages in Docker
Replace tsc with esbuild for building @multica/sdk and @multica/store
in the Docker builder stage. esbuild resolves extensionless imports
that Node.js ESM cannot handle at runtime, producing self-contained
bundles for each workspace package.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 17:34:40 +08:00

79 lines
2.6 KiB
Docker

# Build stage
FROM node:22-alpine AS builder
# Install pnpm
RUN corepack enable && corepack prepare pnpm@10.28.2 --activate
WORKDIR /app
# Copy package files (pnpm-workspace.yaml needed for catalog resolution)
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY packages/sdk/package.json ./packages/sdk/
COPY packages/store/package.json ./packages/store/
# Install all dependencies (including devDependencies for build)
RUN pnpm install --frozen-lockfile
# Copy workspace packages and bundle them with esbuild (resolves extensionless imports)
COPY packages/sdk/ ./packages/sdk/
COPY packages/store/ ./packages/store/
RUN ./node_modules/.bin/esbuild packages/sdk/src/index.ts \
--bundle --platform=node --format=esm --outfile=packages/sdk/dist/index.js --packages=external && \
./node_modules/.bin/esbuild packages/store/src/index.ts packages/store/src/connection.ts \
--bundle --splitting --platform=node --format=esm --outdir=packages/store/dist --packages=external
# Copy source code
COPY tsconfig.json ./
COPY src ./src
# Build TypeScript (tsc emits JS despite type errors; ignore exit code)
RUN ./node_modules/.bin/tsc || true
# Production stage
FROM node:22-alpine AS production
# Install pnpm
RUN corepack enable && corepack prepare pnpm@10.28.2 --activate
WORKDIR /app
# Copy package files (pnpm-workspace.yaml needed for catalog resolution)
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY packages/sdk/package.json ./packages/sdk/
COPY packages/store/package.json ./packages/store/
# Install production dependencies only
RUN pnpm install --frozen-lockfile --prod
# Copy built workspace packages and patch exports to point to compiled JS
COPY --from=builder /app/packages/sdk/dist ./packages/sdk/dist
COPY --from=builder /app/packages/store/dist ./packages/store/dist
RUN node -e " \
const fs = require('fs'); \
['packages/sdk/package.json', 'packages/store/package.json'].forEach(p => { \
const pkg = JSON.parse(fs.readFileSync(p, 'utf8')); \
if (pkg.exports) { \
for (const [key, val] of Object.entries(pkg.exports)) { \
if (typeof val === 'string') { \
pkg.exports[key] = val.replace('./src/', './dist/').replace('.ts', '.js'); \
} \
} \
} \
fs.writeFileSync(p, JSON.stringify(pkg, null, 2)); \
});"
# Copy built files from builder stage
COPY --from=builder /app/dist ./dist
# Copy static assets (not emitted by tsc)
COPY --from=builder /app/src/gateway/public ./dist/gateway/public
# Set environment variables
ENV NODE_ENV=production
ENV PORT=3000
# Expose the port
EXPOSE 3000
# Run the gateway
CMD ["node", "dist/gateway/main.js"]