Ga naar inhoud

Chrome-renderer instellen voor NextPDF Artisan

De bridge start een lokaal Chrome/Chromium-proces en stuurt het aan via chrome-php/chrome. Gebruik deze pagina om die runtime zo in te stellen dat weergaven naar Portable Document Format (PDF) slagen, en om de juiste keuzes rond containers en de sandbox te maken.

BrowserPool maakt een chrome-php/chromeBrowserFactory aan (optioneel met een expliciet pad naar de binary) en start Chrome met een vaste set vlaggen: headless: true, keepAlive: true, windowSize: [1200, 800], sendSyncDefaultTimeout: renderTimeout * 1000, en de aangepaste vlaggen die op de pagina /integrations/artisan/configuration/ staan vermeld. Vervolgens stuurt de bridge het gestarte proces aan via het Chrome DevTools Protocol (CDP). De bridge maakt geen verbinding met een afzonderlijk Chrome-proces via een remote-debugging-poort, dus er is geen netwerkeindpunt dat je blootstelt of moet authenticeren. Chrome draait als een subproces van de PHP-worker. De test tests/Unit/Artisan/BrowserPoolTest.php::getBrowserCreatesAndReusesInstanceWithExpectedOptions verifieert precies deze startopties.

Installeer een Chrome- of Chromium-build die de worker-gebruiker kan uitvoeren:

Terminal window
# Debian / Ubuntu
apt-get install -y chromium
# RHEL / Fedora
dnf install -y chromium
# Alpine (containers)
apk add --no-cache chromium nss freetype harfbuzz ttf-freefont

Controleer of de browser headless draait als de worker-gebruiker:

Terminal window
chromium --headless --dump-dom about:blank

Exitcode 0 met een leeg Document Object Model (DOM) betekent dat de binary en de bijbehorende gedeelde bibliotheken aanwezig zijn. Een exitcode die niet nul is, levert dezelfde fout op die de bridge als een ChromeRenderException doorgeeft. Los die hier eerst op.

Automatische detectie (de standaardinstelling van chrome-php/chrome) werkt wanneer een binary op een standaardpad staat. Voor deterministisch productiegedrag leg je het expliciet vast:

$config = new ChromeRendererConfig(
chromeBinaryPath: '/usr/bin/chromium',
);

of via array-configuratie:

$config = ChromeRendererConfig::fromArray([
'chrome_binary' => '/usr/bin/chromium',
]);

In een container kan de besturingssysteemsandbox van Chrome vaak niet initialiseren als root / process identifier (PID) 1 zonder extra kernel-capabilities. Je hebt twee opties:

  1. Behoud de sandbox (aanbevolen). Voer de worker uit als een niet-root-gebruiker en geef de container de capabilities die de sandbox van Chrome nodig heeft (doorgaans SYS_ADMIN, of een seccomp-profiel dat het aanmaken van user-namespaces toestaat). Hiermee blijft de procesisolatie van Chrome intact.
  2. Schakel de sandbox uit. Stel no_sandbox: true in. Chrome start met --no-sandbox. Hiermee verwijder je de procesisolatiesandbox van Chrome: een daadwerkelijke verzwakking van de afscherming, geen cosmetische vlag. Gebruik dit alleen waar de sandbox niet kan worden ingeschakeld, voer Chrome uit als een niet-root-gebruiker binnen een beperkte container en behandel de implementatie als een configuratie die een hogere mate van vertrouwen in de invoer vereist. De netwerkbarrières van de bridge, het Content Security Policy (CSP) en de CDP-blokkering blijven in beide gevallen van kracht, maar zijn geen vervanging voor procesisolatie. Dit sluit aan bij de OWASP ASVS-richtlijnen voor minimale rechten en isolatie bij het weergeven van niet-vertrouwde inhoud.

De volledige beschrijving van de afbakening, inclusief wat de sandbox wel en niet beschermt, staat op de pagina /integrations/artisan/security-and-operations/. Deze pagina stelt niet dat het uitschakelen van de sandbox veilig is.

FROM php:8.4-cli
RUN apt-get update && apt-get install -y --no-install-recommends \
chromium fonts-liberation \
&& rm -rf /var/lib/apt/lists/*
RUN useradd -m -u 10001 worker
USER worker
ENV CHROME_BINARY=/usr/bin/chromium
# Set CHROME_NO_SANDBOX=1 only if the sandbox cannot be enabled in your runtime.

Voer de worker uit als worker (gebruikers-ID 10001), niet als root. De bridge past de vlag --disable-dev-shm-usage al toe, waarmee de crash door een kleine /dev/shm wordt voorkomen die in containers zonder verdere afstemming vaak voorkomt.

De bridge blokkeert het ophalen van externe lettertypen (--disable-remote-fonts en CSP). Installeer de lettertypen die je nodig hebt op de besturingssysteemlaag, of neem ze op als data:-Uniform Resource Identifier (URI) @font-face-bronnen binnen defaultCss of de Hypertext Markup Language (HTML). Voor uitvoer in het Chinees, Japans en Koreaans (CJK) is een CJK-lettertypepakket nodig (bijvoorbeeld fonts-noto-cjk) dat in de image is geïnstalleerd.

Gebruik deze zelfstandige probe om het volledige bridgepad uit te oefenen zonder de hostapplicatie:

chrome-health.php
<?php
declare(strict_types=1);
use NextPDF\Artisan\ChromeHtmlRenderer;
use NextPDF\Artisan\ChromeRendererConfig;
require __DIR__ . '/vendor/autoload.php';
$renderer = new ChromeHtmlRenderer(
ChromeRendererConfig::fromArray([
'chrome_binary' => getenv('CHROME_BINARY') ?: null,
'no_sandbox' => (bool) getenv('CHROME_NO_SANDBOX'),
]),
);
$result = $renderer->render('<p>ok</p>', 200.0, 0.0);
fwrite(STDOUT, strlen($result->getPdfData()) > 0 ? "CHROME_OK\n" : "CHROME_EMPTY\n");
$renderer->close();

CHROME_OK bevestigt dat starten, weergeven en importeren werken. Een opgeworpen uitzondering bevat de precieze fout. Zoek de bijbehorende vermelding op de pagina /integrations/artisan/troubleshooting/. Koppel deze probe als readiness-controle in georkestreerde implementaties.

  • Voer Chrome uit als een speciale niet-root-gebruiker.
  • Stel een geheugenlimiet op de host in; de bridge begrenst de groei met een herstart na 100 weergaven, maar een bovengrens op de host blijft vereist.
  • Combineer render_timeout met een upstream-aanvraagbudget voor elk pad dat door niet-vertrouwde invoer bereikbaar is.
  • Stel geen Chrome remote-debugging-poort bloot. De bridge gebruikt er geen, en een open CDP-poort is een niet-geauthenticeerd besturingskanaal.
SymptoomWaarschijnlijke oorzaakWaar te kijken
ChromeNotAvailableExceptionchrome-php/chrome niet geïnstalleerd/integrations/artisan/install/
ChromeRenderException bij de eerste weergaveBinary ontbreekt / sandbox kan niet worden geïnitialiseerdDeze pagina; /integrations/artisan/troubleshooting/
Leeg PDF-bestandGeen zichtbaar vak / Chrome-crash/integrations/artisan/troubleshooting/
Lege externe afbeeldingenNetwerk is bewust geblokkeerd/integrations/artisan/security-and-operations/
Periodieke latentiepiekHerstart na 100 weergaven/integrations/artisan/production-usage/
  • /integrations/artisan/install/
  • /integrations/artisan/configuration/
  • /integrations/artisan/security-and-operations/
  • /integrations/artisan/troubleshooting/
  • /integrations/artisan/production-usage/