Skip to content

fix(docker): install node + chromium + puppeteer for Browsershot PDF rendering - #65

Merged
DGINXREAL merged 1 commit into
mainfrom
fix/pdf-browsershot-runtime
Aug 9, 2026
Merged

fix(docker): install node + chromium + puppeteer for Browsershot PDF rendering#65
DGINXREAL merged 1 commit into
mainfrom
fix/pdf-browsershot-runtime

Conversation

@DGINXREAL

Copy link
Copy Markdown
Member

Problem

Production PDF rendering fails with exit code 127:

sh: 1: npm: not found
sh: 1: node: not found

spatie/laravel-pdf uses the Browsershot driver, which launches a headless browser via Node at runtime. The dunglas/frankenphp:1-php8.4 runtime image ships neither Node nor Chromium (Node only existed in the discarded frontend-builder stage), so every PDF render 500s. This affects both the new scheduled-report PDF attachments and the pre-existing on-demand Download PDF (Statistics / ReportController). Email + CSV delivery are unaffected.

Fix

Add the Browsershot runtime requirements to the image (stage 2):

  • chromium (system browser at /usr/bin/chromium — matches config/laravel-pdf.php's chrome_path default), plus fonts-liberation + fonts-noto-color-emoji to avoid missing-glyph boxes.
  • nodejs + npm.
  • puppeteer installed globally (Browsershot resolves it via npm root -g) with PUPPETEER_SKIP_DOWNLOAD=true so it reuses the system Chromium instead of downloading its own. no_sandbox=true is already the config default.

Verification

  • End-to-end on the exact base image: Puppeteer launches /usr/bin/chromium (--no-sandbox --disable-dev-shm-usage) and renders a PDF (node v20.19.2, chromium 151, puppeteer global).
  • Full docker build of the app image succeeds.

Notes / follow-ups

  • Trivy: adding Chromium + Node enlarges the CVE surface; the image scan (CRITICAL/HIGH, ignore-unfixed) may surface new fixable CVEs. If so, bump the base image (--pull) or add documented .trivyignore entries.
  • /dev/shm: Browsershot does not pass --disable-dev-shm-usage by default. For robustness with larger PDFs, set shm_size: '1gb' on the app service in the (server-managed) compose file. Current report PDFs are small, so the 64 MB default is normally fine.

🤖 Generated with Claude Code

…rendering

Production PDF rendering (spatie/laravel-pdf via Browsershot) failed with
'node: not found' (exit 127): the frankenphp runtime image had no Node/Chromium.
Add system chromium (/usr/bin/chromium — matches laravel-pdf chrome_path),
nodejs+npm, emoji/latin fonts, and Puppeteer installed globally with its own
Chromium download skipped (uses the system chromium, no_sandbox=true).

Verified end-to-end on the base image: puppeteer launches /usr/bin/chromium
(--no-sandbox --disable-dev-shm-usage) and renders a PDF; full image builds.
Affects both scheduled-report PDF attachments and the on-demand Download PDF.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@DGINXREAL
DGINXREAL requested a review from noidee-dev as a code owner August 9, 2026 07:08
@DGINXREAL
DGINXREAL merged commit 4d2c439 into main Aug 9, 2026
3 checks passed
@DGINXREAL
DGINXREAL deleted the fix/pdf-browsershot-runtime branch August 9, 2026 07:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant