# --- Build stage --- FROM node:22-alpine AS builder WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . RUN npm run build # --- Runtime stage --- FROM node:22-alpine WORKDIR /app COPY --from=builder /app/build ./build # The lockfile comes along so the runtime deps are the ones that were tested. With only # package.json here, `npm install` re-resolved the `^`-ranged dependencies at build time, so an # image rebuilt days later could ship different code than the one that passed the checks — the # kind of difference that only shows up on the event server. COPY --from=builder /app/package.json /app/package-lock.json ./ RUN npm ci --omit=dev # Run as the image's built-in non-root `node` user. RUN chown -R node:node /app USER node EXPOSE 3001 ENV PORT=3001 HOST=0.0.0.0 CMD ["node", "build"]