# ----------------------- # Base image # ----------------------- FROM node:18-alpine AS base WORKDIR /app # ----------------------- # Install dependencies # ----------------------- FROM base AS deps WORKDIR /deps COPY package*.json ./ RUN npm ci # ----------------------- # Build stage # ----------------------- FROM base AS builder WORKDIR /build COPY . . # copy deps only (faster + deterministic) COPY --from=deps /deps/node_modules ./node_modules RUN npm run build # ----------------------- # Production dependencies (Nitro externalizes ipx, sharp, etc.) # ----------------------- FROM base AS prod-deps WORKDIR /deps COPY package*.json ./ RUN npm ci --omit=dev # ----------------------- # Production runtime # ----------------------- FROM node:18-alpine AS runner WORKDIR /app # sharp (used by ipx) needs libc compatibility on Alpine RUN apk add --no-cache libc6-compat # create non-root user RUN addgroup -S appgroup && adduser -S appuser -G appgroup COPY --from=builder /build/.output ./.output COPY --from=prod-deps /deps/node_modules ./node_modules USER appuser ENV NODE_ENV=production EXPOSE 3000 CMD ["node", ".output/server/index.mjs"]