# ============================================================ # STAGE 1: Build Frontend + Backend # ============================================================ FROM node:22-alpine AS builder # Install system dependencies for sharp and pdf processing RUN apk add --no-cache \ python3 \ py3-pip \ make \ g++ \ gcc \ libc-dev \ vips-dev \ poppler-utils \ pkgconfig WORKDIR /app # Install pnpm and node-gyp globally RUN npm install -g pnpm@10.4.1 node-gyp # Copy package files COPY package.json pnpm-lock.yaml ./ COPY patches/ ./patches/ # Install dependencies (with node-gyp available) RUN pnpm install --frozen-lockfile # Copy source code COPY . . # Build frontend + backend RUN pnpm build # ============================================================ # STAGE 2: Production image # ============================================================ FROM node:22-alpine AS production # Install runtime dependencies RUN apk add --no-cache \ poppler-utils \ vips \ curl WORKDIR /app # Install pnpm RUN npm install -g pnpm@10.4.1 # Copy package files COPY package.json pnpm-lock.yaml ./ COPY patches/ ./patches/ # Install production dependencies only (no build tools needed for prod deps) RUN apk add --no-cache python3 make g++ gcc libc-dev vips-dev pkgconfig && \ npm install -g node-gyp && \ pnpm install --frozen-lockfile --prod && \ apk del make g++ gcc libc-dev pkgconfig # Copy built assets from builder COPY --from=builder /app/dist ./dist COPY --from=builder /app/client/dist ./client/dist # Copy drizzle migrations COPY drizzle/ ./drizzle/ COPY drizzle.config.ts ./ # Create uploads directory RUN mkdir -p /app/uploads EXPOSE 3000 CMD ["node", "dist/index.js"]