# --- Stage 1: Build frontend --- FROM node:20-slim AS frontend-build WORKDIR /app/frontend COPY frontend/package.json frontend/package-lock.json* frontend/.npmrc* ./ RUN npm install COPY frontend/ ./ COPY backend/src/shared/ ../backend/src/shared/ # The shared files import npm packages (e.g. `shiki`) that are declared in the # frontend package.json. When rollup resolves those imports from /app/backend/ # it walks up the tree looking for node_modules; without this symlink it never # reaches /app/frontend/node_modules and the build fails with # "Rollup failed to resolve import 'shiki'". RUN ln -s /app/frontend/node_modules /app/backend/node_modules RUN npm run build # --- Stage 2: Build backend --- FROM node:20-slim AS backend-build WORKDIR /app COPY backend/package.json backend/package-lock.json* ./ RUN npm install COPY backend/ ./ RUN npx tsc # --- Stage 3: Production image --- FROM node:20-slim RUN apt-get update && apt-get install -y --no-install-recommends \ libglib2.0-0 \ libnss3 \ libnspr4 \ libatk1.0-0 \ libatk-bridge2.0-0 \ libcups2 \ libdrm2 \ libdbus-1-3 \ libxkbcommon0 \ libatspi2.0-0 \ libxcomposite1 \ libxdamage1 \ libxfixes3 \ libxrandr2 \ libgbm1 \ libpango-1.0-0 \ libcairo2 \ libasound2 \ libwayland-client0 \ fonts-noto-color-emoji \ fonts-liberation \ && rm -rf /var/lib/apt/lists/* WORKDIR /app # Copy compiled backend + prod dependencies COPY backend/package.json backend/package-lock.json* ./ RUN npm install --omit=dev COPY --from=backend-build /app/dist ./dist # Install Playwright Chromium browser binaries. # We invoke the playwright CLI through its package path instead of `npx # playwright` because the `.bin/playwright` symlink clashes with the one # shipped by @playwright/test (dev-only) and isn't recreated when npm is run # with --omit=dev. ENV PLAYWRIGHT_BROWSERS_PATH=/app/browsers RUN node node_modules/playwright/cli.js install chromium # Copy frontend build COPY --from=frontend-build /app/frontend/dist ./frontend-dist # Copy CSS source files for the HTML renderer COPY frontend/src/styles/ ./frontend-styles/ ENV PORT=8080 ENV NODE_ENV=production ENV ENABLE_PDF=true EXPOSE 8080 CMD ["node", "dist/server.js"]