Thiết lập trình kết xuất Chrome cho NextPDF Artisan
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”Cầu nối khởi chạy và điều khiển một tiến trình Chrome/Chromium cục bộ thông qua chrome-php/chrome. Hãy dùng trang này để thiết lập môi trường chạy đó, đảm bảo các lần kết xuất Portable Document Format (PDF) thành công và giúp đưa ra quyết định phù hợp về container và sandbox.
Cách cầu nối giao tiếp với Chrome
Phần tiêu đề “Cách cầu nối giao tiếp với Chrome”BrowserPool tạo một chrome-php/chromeBrowserFactory (có thể kèm đường dẫn tệp nhị phân được chỉ định rõ) và khởi chạy Chrome với một bộ cờ cố định: headless: true, keepAlive: true, windowSize: [1200, 800], sendSyncDefaultTimeout: renderTimeout * 1000, cùng các cờ tùy chỉnh được liệt kê trên trang /integrations/artisan/configuration/. Sau đó, cầu nối điều khiển tiến trình vừa khởi chạy qua Chrome DevTools Protocol (CDP). Nó không kết nối tới một tiến trình Chrome riêng biệt qua cổng gỡ lỗi từ xa, nên không có điểm cuối mạng nào cần mở hoặc xác thực. Chrome chạy như một tiến trình con của worker PHP. Bài kiểm thử tests/Unit/Artisan/BrowserPoolTest.php::getBrowserCreatesAndReusesInstanceWithExpectedOptions kiểm chứng chính xác các tùy chọn khởi chạy này.
Chuẩn bị tệp nhị phân
Phần tiêu đề “Chuẩn bị tệp nhị phân”Cài đặt bản dựng Chrome hoặc Chromium mà người dùng worker có quyền thực thi:
# Debian / Ubuntuapt-get install -y chromium
# RHEL / Fedoradnf install -y chromium
# Alpine (containers)apk add --no-cache chromium nss freetype harfbuzz ttf-freefontXác minh rằng tệp nhị phân có thể chạy ở chế độ headless dưới danh nghĩa người dùng worker:
chromium --headless --dump-dom about:blankMã thoát 0 kèm một Document Object Model (DOM) rỗng cho biết tệp nhị phân và các thư viện dùng chung của nó đều hiện diện. Mã thoát khác 0 sẽ được cầu nối báo lên dưới dạng ChromeRenderException. Hãy xử lý vấn đề ngay ở bước này trước.
Trỏ cầu nối tới tệp nhị phân
Phần tiêu đề “Trỏ cầu nối tới tệp nhị phân”Cơ chế tự động phát hiện (mặc định của chrome-php/chrome) hoạt động khi tệp nhị phân nằm trên đường dẫn chuẩn. Để hành vi trong môi trường production có tính tất định, hãy ghim đường dẫn một cách rõ ràng:
$config = new ChromeRendererConfig( chromeBinaryPath: '/usr/bin/chromium',);hoặc thông qua cấu hình dạng mảng:
$config = ChromeRendererConfig::fromArray([ 'chrome_binary' => '/usr/bin/chromium',]);Thiết lập container và quyết định về sandbox
Phần tiêu đề “Thiết lập container và quyết định về sandbox”Trong container, sandbox cấp hệ điều hành của Chrome thường không thể khởi tạo khi chạy với tư cách root / process identifier (PID) 1 nếu thiếu các capability bổ sung của kernel. Bạn có hai lựa chọn:
- Giữ sandbox (nên dùng). Chạy worker với tư cách người dùng không phải root, đồng thời cấp cho container những capability mà sandbox của Chrome cần (thường là
SYS_ADMIN, hoặc một seccomp profile cho phép tạo user-namespace). Cách này giữ nguyên cơ chế cô lập tiến trình của Chrome. - Tắt sandbox. Đặt
no_sandbox: true. Chrome khởi chạy với--no-sandbox. Việc này loại bỏ sandbox dùng để cô lập tiến trình của Chrome: đây thực sự là mức suy giảm về khả năng ngăn chặn, không phải một cờ chỉ mang tính hình thức. Chỉ dùng cách này trong môi trường không thể bật sandbox, chạy Chrome với tư cách người dùng không phải root bên trong một container bị giới hạn, và xem cách triển khai này là trường hợp đòi hỏi mức tin cậy cao hơn đối với dữ liệu đầu vào. Các rào chắn mạng của cầu nối, gồm Content Security Policy (CSP) và việc chặn CDP, vẫn có hiệu lực trong cả hai trường hợp, nhưng chúng không thể thay thế cho cơ chế cô lập tiến trình. Điều này phù hợp với hướng dẫn về đặc quyền tối thiểu và cô lập của OWASP ASVS khi kết xuất nội dung không đáng tin cậy.
Phần mô tả đầy đủ về ranh giới, bao gồm những gì sandbox bảo vệ và không bảo vệ, nằm trên trang /integrations/artisan/security-and-operations/. Trang này không khẳng định việc tắt sandbox là an toàn.
Mẫu container tham khảo
Phần tiêu đề “Mẫu container tham khảo”FROM php:8.4-cliRUN apt-get update && apt-get install -y --no-install-recommends \ chromium fonts-liberation \ && rm -rf /var/lib/apt/lists/*RUN useradd -m -u 10001 workerUSER workerENV CHROME_BINARY=/usr/bin/chromium# Set CHROME_NO_SANDBOX=1 only if the sandbox cannot be enabled in your runtime.Chạy worker với tư cách worker (user ID 10001), không phải root. Cầu nối đã áp dụng sẵn cờ --disable-dev-shm-usage, nhờ đó tránh được lỗi sập do /dev/shm quá nhỏ, một vấn đề thường gặp trong các container nếu không tinh chỉnh thêm.
Phông chữ
Phần tiêu đề “Phông chữ”Cầu nối chặn việc tải phông chữ từ xa (--disable-remote-fonts và CSP). Hãy cài đặt các phông chữ cần dùng ở lớp hệ điều hành, hoặc nhúng chúng dưới dạng nguồn data: Uniform Resource Identifier (URI) cho @font-face bên trong defaultCss hoặc Hypertext Markup Language (HTML). Đầu ra tiếng Trung, tiếng Nhật và tiếng Hàn (CJK) cần cài đặt một gói phông chữ CJK (ví dụ fonts-noto-cjk) trong image.
Kiểm tra tình trạng hoạt động
Phần tiêu đề “Kiểm tra tình trạng hoạt động”Hãy dùng đầu dò độc lập này để chạy thử toàn bộ luồng của cầu nối mà không cần ứng dụng máy chủ:
<?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 xác nhận việc khởi chạy, kết xuất và import. Nếu có ngoại lệ được ném ra, đó chính là lỗi cụ thể cần xử lý. Hãy đối chiếu lỗi đó trên trang /integrations/artisan/troubleshooting/. Hãy tích hợp đầu dò này thành một bước kiểm tra mức sẵn sàng trong các triển khai được điều phối.
Ghi chú về cô lập tài nguyên
Phần tiêu đề “Ghi chú về cô lập tài nguyên”- Chạy Chrome dưới một người dùng riêng không phải root.
- Hãy đặt giới hạn bộ nhớ ở cấp máy chủ; cầu nối có kiểm soát mức tăng trưởng bằng cách khởi động lại sau mỗi 100 lần kết xuất, nhưng vẫn cần một mức trần ở cấp máy chủ.
- Hãy kết hợp
render_timeoutvới hạn mức thời gian cho yêu cầu ở lớp trên trong bất kỳ luồng nào mà dữ liệu đầu vào không đáng tin cậy có thể tiếp cận. - Không mở cổng gỡ lỗi từ xa của Chrome. Cầu nối không dùng cổng nào như vậy, và cổng CDP bị mở là một kênh điều khiển không được xác thực.
Các kiểu lỗi và cách khắc phục sự cố
Phần tiêu đề “Các kiểu lỗi và cách khắc phục sự cố”| Triệu chứng | Nguyên nhân có khả năng | Xem tại |
|---|---|---|
ChromeNotAvailableException | chrome-php/chrome chưa được cài đặt | /integrations/artisan/install/ |
ChromeRenderException ở lần kết xuất đầu tiên | Thiếu tệp nhị phân / sandbox không thể khởi tạo | Trang này; /integrations/artisan/troubleshooting/ |
| PDF rỗng | Không có hộp hiển thị nào / Chrome bị sập | /integrations/artisan/troubleshooting/ |
| Hình ảnh từ xa bị trống | Mạng bị chặn theo thiết kế | /integrations/artisan/security-and-operations/ |
| Độ trễ tăng vọt theo chu kỳ | Khởi động lại sau mỗi 100 lần kết xuất | /integrations/artisan/production-usage/ |
Xem thêm
Phần tiêu đề “Xem thêm”- /integrations/artisan/install/
- /integrations/artisan/configuration/
- /integrations/artisan/security-and-operations/
- /integrations/artisan/troubleshooting/
- /integrations/artisan/production-usage/