# syntax=docker/dockerfile:1 FROM node:22-bookworm-slim AS runtime ENV NODE_ENV=production \ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 \ CHROMIUM_PATH=/usr/bin/chromium \ PORT=8080 \ HOME=/home/appuser \ LANG=C.UTF-8 \ LC_ALL=C.UTF-8 RUN apt-get update \ && apt-get install -y --no-install-recommends \ ca-certificates \ chromium \ curl \ fonts-dejavu-core \ fonts-liberation \ fonts-noto-cjk \ fonts-noto-color-emoji \ fonts-noto-core \ tini \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci --omit=dev && npm cache clean --force COPY src ./src COPY public ./public RUN useradd --create-home --uid 10001 appuser \ && chown -R appuser:appuser /app /home/appuser USER appuser EXPOSE 8080 HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ CMD node -e "fetch('http://127.0.0.1:8080/healthz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" ENTRYPOINT ["/usr/bin/tini", "--"] CMD ["node", "src/server.js"] # Test image: includes dev dependencies and the test suite. FROM runtime AS test USER root # NODE_ENV=production is inherited from the runtime stage, which would make # npm skip dev dependencies such as pdfjs-dist that the smoke test needs. RUN npm ci --include=dev && npm cache clean --force COPY --chown=appuser:appuser test ./test USER appuser CMD ["npm", "test"] # Default production target. FROM runtime AS production