# ---- Build stage ---- FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY tsconfig.json ./ COPY src/ ./src/ RUN npm run build # ---- Production stage ---- FROM node:20-alpine # tini as init process + chromium for Playwright + curl for healthcheck RUN apk add --no-cache \ tini \ chromium \ nss \ freetype \ freetype-dev \ harfbuzz \ ca-certificates \ ttf-freefont \ curl # Tell Playwright to use the system Chromium instead of downloading its own ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 ENV PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium-browser ENV NODE_ENV=production # Non-root user RUN addgroup -S abe && adduser -S abe -G abe WORKDIR /app COPY package*.json ./ RUN npm ci --omit=dev && chown -R abe:abe /app COPY --from=builder --chown=abe:abe /app/dist ./dist # Runtime directories for data, reports and logs RUN mkdir -p data reports logs && chown -R abe:abe data reports logs USER abe EXPOSE 3001 HEALTHCHECK --interval=30s --timeout=10s --start-period=15s --retries=3 \ CMD curl -f http://localhost:3001/health/live || exit 1 ENTRYPOINT ["/sbin/tini", "--"] CMD ["node", "dist/main.js"]