Konteneryzacja aplikacji NextPDF
W skrócie
Dział zatytułowany „W skrócie”Chcesz małego, odtwarzalnego obrazu Docker, który uruchamia natywny silnik rdzenia
NextPDF działający w ramach procesu — composer require nextpdf/core, generujący
pliki PDF wewnątrz Twojego procesu PHP. Ta strona buduje dokładnie to: obraz php:8.4
tylko z rozszerzeniami, których silnik faktycznie potrzebuje, bez zależności
deweloperskich w warstwie końcowej, z dołączonymi czcionkami, użytkownikiem
uruchomieniowym non-root, opcache dostrojonym pod produkcję oraz krokiem weryfikacji,
który obala kompilację, jeśli czegoś brakuje.
Ta strona jest wyłącznie dla natywnego silnika. Mostek Chrome
(writeHtmlChrome przez nextpdf/artisan) oraz serwer Connect to osobne środowiska
uruchomieniowe z własnymi, cięższymi obrazami — instalacja headless Chromium dla
mostka, długo działająca usługa dla Connect. Nie dodawaj przeglądarki ani serwera do
tego obrazu; natywny silnik nie potrzebuje żadnego z nich.
Zanim zaczniesz, potwierdź, że te elementy są na miejscu:
- Twoja aplikacja ma zatwierdzone
composer.jsonicomposer.lock, znextpdf/corejako zależnością. - Masz pliki czcionek, które zamierzasz osadzić, i masz prawo je osadzić.
- Możesz uruchomić
docker buildwzględem katalogu swojej aplikacji.
To poradnik operacyjny. PHP jest tu prawie nieobecne; praca tkwi w Dockerfile i kilku ustawieniach środowiskowych.
Czego faktycznie wymaga silnik
Dział zatytułowany „Czego faktycznie wymaga silnik”Obraz musi spełnić rzeczywiste ograniczenia platformowe silnika, nic więcej.
Odczytując je wprost z pakietu, nextpdf/core wymaga php: >=8.4 <9.0 oraz tych
rozszerzeń PHP:
| Rozszerzenie | Dlaczego silnik go potrzebuje |
|---|---|
ext-mbstring | Obsługa łańcuchów wielobajtowych dla tekstu i kodowań |
ext-intl | Wsparcie Unicode, ustawień regionalnych i internacjonalizacji |
ext-gd | Dekodowanie i przetwarzanie obrazów rastrowych |
ext-openssl | Kryptografia do podpisywania i bezpiecznego haszowania |
ext-zlib | Kompresja strumieni (Flate) obiektów PDF |
ext-curl | Klient HTTP do wychodzących wywołań silnika |
Odwzoruj je na oficjalny obraz php:8.4. openssl, curl oraz zlib są już
wkompilowane w oficjalny obraz PHP, więc nie uruchamiasz dla nich
docker-php-ext-install. mbstring, gd oraz intl nie są dołączone i muszą
zostać zainstalowane, a każde z nich potrzebuje najpierw obecnych systemowych
nagłówków deweloperskich — mbstring dodatkowo potrzebuje zależności kompilacyjnej
libonig-dev (Oniguruma). Nie dodawaj rozszerzeń silnika, których pakiet nie wymienia
— każde dodatkowe docker-php-ext-install to czas kompilacji i powierzchnia ataku,
których nie potrzebujesz. Jedynym rozszerzeniem spoza silnika, które ten obraz
instaluje, jest opcache: to rozszerzenie wydajności w czasie działania, niewłączone
domyślnie na oficjalnym obrazie, a poniższe dostrojenie opcache zależy od jego obecności
(zobacz „Opcache pod produkcję”).
Produkcyjny Dockerfile
Dział zatytułowany „Produkcyjny Dockerfile”To kompilacja dwuetapowa. Pierwszy etap instaluje zależności Composera z wyłączonymi pakietami deweloperskimi; drugi etap to odchudzony obraz uruchomieniowy, który jest wysyłany.
Najpierw dodaj .dockerignore obok Dockerfile. Jego głównym zadaniem jest całkowite
trzymanie środowiska hosta — zbudowanego na hoście vendor/, lokalnych plików
sekretów i pamięci podręcznych kompilacji — poza kontekstem kompilacji, aby
COPY . /var/www/app wysyłał tylko to, co zamierzasz: mniejsze, szybsze i
bezpieczniejsze kompilacje, które nie mogą wyciec lokalnych sekretów .env ani
przenieść megabajtów hostowego vendor/ do obrazu.
Wykluczenie vendor/ ma znaczenie także dlatego, że COPY katalogu to scalenie,
a nie zastąpienie. Poniższy Dockerfile uruchamia RUN rm -rf /var/www/app/vendor
przed COPY --from=vendor ... /var/www/app/vendor, więc w tym obrazie hostowy
vendor/ nigdy nie może przetrwać pod czystym drzewem zależności. Jeśli jednak
kiedykolwiek usuniesz to zabezpieczenie rm -rf, zbudowany na hoście vendor/ w
kontekście trafiłby tam jako pierwszy, a kopia z etapu vendor nadpisałaby tylko te
ścieżki, które zawiera czyste drzewo — wszelkie dodatkowe pliki hosta (nieaktualny lub
deweloperski pakiet, osierocona klasa) przetrwałyby wtedy pod spodem. Trzymanie
vendor/ poza kontekstem zamyka tę lukę niezależnie od rm -rf.
# .dockerignore — keep the host environment out of the build context.vendor/.git/.env.env.local.env.*.localvar/cache/storage/node_modules/*.logWyklucz rzeczywiste lokalne pliki sekretów (.env, .env.local, .env.*.local), a
nie ryczałtowe .env.* — ten symbol wieloznaczny porzuca również niesekretne szablony,
takie jak .env.example, które chcesz wysłać, aby obraz niósł udokumentowaną bazę
konfiguracji. Trzymaj w kontekście dowolny zatwierdzony, niesekretny szablon env;
wyklucz wyłącznie pliki, które faktycznie przechowują lokalne sekrety.
# syntax=docker/dockerfile:1
# ---- Stage 1: dependencies (no dev) ---------------------------------------FROM composer:2 AS vendor
WORKDIR /appCOPY composer.json composer.lock ./
# Install production dependencies only. --no-dev excludes phpunit, phpstan,# infection, and the other require-dev tooling from the shipped image.# --optimize-autoloader builds a class map for the *vendor* tree here; the# application's own classes are not present in this stage yet, so they are# optimized after the source copy in the runtime stage (see below).RUN composer install \ --no-dev \ --no-interaction \ --no-progress \ --prefer-dist \ --optimize-autoloader \ --no-scripts
# ---- Stage 2: runtime ------------------------------------------------------FROM php:8.4-cli AS runtime
# System headers for the gd, intl, and mbstring extensions that need compiling.# The PHP image already provides openssl, curl, and zlib, so those are NOT# listed; gd, intl, and mbstring are installed below. opcache has no system# headers and is installed in the same step. mbstring is built against# Oniguruma, so libonig-dev is in the *-dev set and its runtime lib (libonig5)# is preserved by the same detection below.## Build the *-dev headers (which pull in the runtime libs), compile the# extensions, then mark only the runtime shared libraries the extensions# actually link against so they survive the --auto-remove purge of the headers.# Removing libicu / libpng / libjpeg / libfreetype / libonig here would unlink# intl.so, gd.so, or mbstring.so at runtime ("undefined symbol" / "cannot open# shared object file").RUN set -eux; \ savedAptMark="$(apt-mark showmanual)"; \ apt-get update; \ apt-get install -y --no-install-recommends \ libicu-dev \ libpng-dev \ libjpeg62-turbo-dev \ libfreetype6-dev \ libonig-dev; \ docker-php-ext-configure gd --with-freetype --with-jpeg; \ docker-php-ext-install -j"$(nproc)" gd intl mbstring opcache; \ # Detect the runtime .so dependencies of the just-built extensions and # mark them manual so --auto-remove keeps them while dropping the headers. apt-mark auto '.*' > /dev/null; \ apt-mark manual $savedAptMark > /dev/null; \ find /usr/local/lib/php/extensions -type f -name '*.so' -exec \ sh -c 'ldd "$1" 2>/dev/null \ | awk "/=>/ { print \$3 }" \ | grep -E "^/" \ | xargs -r dpkg-query -S 2>/dev/null \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual' _ {} \; ; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ rm -rf /var/lib/apt/lists/*
# Production opcache settings (see the opcache section below). The opcache# extension is installed above (docker-php-ext-install opcache); this file only# tunes it.COPY docker/opcache.ini /usr/local/etc/php/conf.d/opcache.ini
# A static Composer binary for the one optimized-autoloader rebuild below. It is# copied into the build but the final stage runs no Composer at request time.COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/app
# Application code, then the vendor tree from the dependency stage. The .dockerignore# should already keep a host vendor/ out of the context; the rm here is a second line# of defense so a stale host-built vendor/ can never merge under the clean one (a# directory COPY merges, it does not replace).COPY . /var/www/appRUN rm -rf /var/www/app/vendorCOPY --from=vendor /app/vendor /var/www/app/vendor
# Now that the application source is present, regenerate the optimized class map# so the APP's own classes are in the optimized autoloader, not just the vendor# packages. --no-dev keeps require-dev out; --no-scripts avoids running# application hooks during the image build.RUN composer dump-autoload \ --optimize \ --no-dev \ --no-interaction \ --no-scripts \ && rm -f /usr/bin/composer
# The bundled fonts live at /var/www/app/resources/fonts. The native engine does# NOT read any font-path environment variable — the entrypoint registers that# directory in PHP (see "Bundle fonts into the image" below). There is no ENV# line for fonts here.
# Run as a non-root user (see the non-root section below).RUN useradd --system --no-create-home --uid 10001 appuser \ && chown -R appuser:appuser /var/www/appUSER appuser
CMD ["php", "bin/generate.php"]Etap zależności działa z --no-scripts, więc żaden poinstalacyjny hak aplikacji nie
uruchamia się względem niekompletnego drzewa; uruchom dowolny krok kompilacji
aplikacji (kompilację zasobów, rozgrzanie pamięci podręcznej) na późniejszym etapie,
po skopiowaniu kodu.
Wieloetapowa instalacja Composera (bez zależności deweloperskich)
Dział zatytułowany „Wieloetapowa instalacja Composera (bez zależności deweloperskich)”Wysyłany obraz nie może zawierać narzędzi deweloperskich. Flaga --no-dev w
composer install to linia nośna: pomija wszystko z require-dev w nextpdf/core i
Twojej aplikacji — runner testów, analizator statyczny i narzędzia do mutacji — z
których żadne nie ma miejsca na produkcji. Połącz ją z --optimize-autoloader, aby
autoloader był wygenerowaną mapą klas, a nie skanem systemu plików przy każdym żądaniu.
Skopiuj composer.json oraz composer.lock przed resztą źródła, aby Docker
buforował warstwę zależności i rozwiązywał je ponownie tylko wtedy, gdy plik lock się
zmieni. Ponieważ ta pierwsza instalacja działa wyłącznie względem pliku lock — bez
źródła aplikacji — --optimize-autoloader buduje tam mapę klas tylko dla drzewa
vendor; własnych klas Twojej aplikacji jeszcze nie ma. Dlatego etap uruchomieniowy
uruchamia composer dump-autoload --optimize --no-dev --no-scripts raz po
skopiowaniu źródła: składa klasy aplikacji do tej samej zoptymalizowanej mapy klas.
Nie uruchamiaj osobnego composer dump-autoload w drzewie roboczym, w którym też
programujesz (zatwierdziłoby to produkcyjną mapę klas do drzewa deweloperskiego);
przebudowa należy do obrazu, po skopiowaniu źródła, jak pokazano powyżej.
Dołącz czcionki do obrazu
Dział zatytułowany „Dołącz czcionki do obrazu”Natywny silnik rozwiązuje czcionki na podstawie plików czcionek, które potrafi
odczytać, a nie na podstawie czcionek zainstalowanych w systemie operacyjnym.
Zainstalowanie pakietów fonts-* lub uruchomienie fc-cache nie daje nic, co mogłaby
zobaczyć ścieżka natywna, więc ten obraz nie instaluje żadnych czcionek systemowych.
Dołącz swoje pliki .ttf / .otf pod resources/fonts/; powyższe
COPY . /var/www/app już przenosi je do obrazu.
Wprowadzenie plików do obrazu to dopiero połowa pracy. Goły natywny silnik nie
odczytuje żadnej zmiennej środowiskowej wyszukiwania czcionek — NEXTPDF_FONTS_PATH
to domyślna wartość klucza konfiguracji fonts_path pakietu nextpdf/laravel
(env('NEXTPDF_FONTS_PATH', resource_path('fonts'))) i jest konsumowana wyłącznie
przez tę integrację frameworka, a nie przez nextpdf/core. Zwykły punkt wejścia
php bin/generate.php z ustawioną jedynie tą zmienną nie rejestruje żadnych czcionek
i renderuje to samo tofu, któremu ten obraz ma zapobiegać. Punkt wejścia musi
zarejestrować dołączony katalog w PHP:
use NextPDF\Typography\FontRegistry;use NextPDF\Core\DocumentFactory;use NextPDF\Graphics\ImageRegistry;
// Register the directory the Dockerfile bundled the fonts into.$registry = new FontRegistry('/var/www/app/resources/fonts');// (equivalently, $registry->addFontDirectory('/var/www/app/resources/fonts');)
$factory = new DocumentFactory($registry, new ImageRegistry(maxCacheBytes: 0));$doc = $factory->create();To cała dockerowa troska o czcionki. Reguły nazewnictwa plików, API rejestru, wzorzec rozgrzewki-i-zablokowania oraz obsługa systemu plików tylko do odczytu — wszystko żyje na dedykowanej stronie; nie duplikuj tego tutaj. Przeczytaj Udostępnianie czcionek dla natywnego silnika w środowisku produkcyjnym, aby poznać pełny wzorzec, i zarejestruj ten sam katalog, który dołączyłeś.
Uruchom jako użytkownik non-root
Dział zatytułowany „Uruchom jako użytkownik non-root”Oficjalne obrazy PHP domyślnie działają jako root. Generator PDF nie potrzebuje
roota, więc utwórz użytkownika nieuprzywilejowanego i przełącz się na niego. Powyższy
Dockerfile dodaje użytkownika systemowego appuser ze stałym wysokim UID (10001),
nadaje mu własność drzewa aplikacji i kończy się USER appuser, aby każdy proces
uruchamiany przez kontener był nieuprzywilejowany.
Utrzymuj aplikację tylko do odczytu w czasie działania, gdzie tylko możesz. Silnik
odczytuje swoje pliki czcionek, a zapisuje jedynie swoje wyjście i opcjonalną pamięć
podręczną sparsowanych czcionek, więc kontener readOnlyRootFilesystem działa,
dopóki ścieżka wyjściowa i dowolny katalog pamięci podręcznej są zapisywalnymi
montowaniami. Połącz to z odjętymi zdolnościami Linuksa oraz flagą no-new-privileges
w Twoim orkiestratorze, aby uzyskać obronę w głąb.
Opcache pod produkcję
Dział zatytułowany „Opcache pod produkcję”Opcache opłaca się dla długowiecznych procesów roboczych PHP — puli FPM lub
procesu mod_php Apache, który obsługuje wiele żądań z jednego rozgrzanego procesu.
Te procesy kompilują Twoje klasy raz i potem nigdy nie sprawdzają plików źródłowych na
gorącej ścieżce, czyli dokładnie to, co kupuje Ci opcache.validate_timestamps=0.
Opcache nie jest włączony od ręki na oficjalnym obrazie php:8.4, więc powyższy
Dockerfile instaluje go przez docker-php-ext-install opcache (możesz równoważnie
użyć docker-php-ext-enable opcache, jeśli rozszerzenie jest już skompilowane).
Poniższy plik conf.d to dostrojenie, a nie krok włączenia — nie robi nic, dopóki
rozszerzenie nie zostanie załadowane. Wyślij go jako dołączenie conf.d
(docker/opcache.ini, skopiowane w Dockerfile):
opcache.enable=1opcache.enable_cli=0opcache.memory_consumption=192opcache.interned_strings_buffer=16opcache.max_accelerated_files=20000opcache.validate_timestamps=0opcache.validate_timestamps=0 oznacza, że pamięć podręczna nigdy ponownie nie
sprawdza plików źródłowych — poprawne dla niezmiennego obrazu, ponieważ jedynym
sposobem zmiany kodu jest nowy obraz. Dostrój memory_consumption oraz
max_accelerated_files do liczby klas Twojej aplikacji.
Pokazane CMD to jednorazowy generator CLI, a opcache.enable_cli=0 jest dla niego
poprawne. Krótkowieczny proces php bin/generate.php startuje, kompiluje, renderuje
raz i kończy, więc pamięć podręczna opkodów, której nie może współdzielić z następnym
żądaniem, nie daje korzyści — pozostaw opcache CLI wyłączony i nie płać żadnego z jego
kosztów pamięci. Opcache zarabia na siebie tam, gdzie proces jest wielokrotnie używany:
SAPI FPM/Apache albo genuinie długo działający proces roboczy CLI (konsument kolejki
lub serwer w stylu RoadRunner). Tylko taki rezydentny proces roboczy CLI ustawiłby
opcache.enable_cli=1; dla jednorazowego generatora tutaj zachowaj 0.
Jeśli prowadzisz konfigurację korzystającą z wstępnego ładowania (preloading)
opcache (długowieczny proces roboczy FPM ze skryptem opcache.preload), ustaw
opcache.preload=/path/to/preload.php i dodaj opcache.preload_user=appuser, aby
wstępne ładowanie działało jako użytkownik nieuprzywilejowany. Bez rzeczywistego
skryptu opcache.preload opcache.preload_user nic nie robi, dlatego nie ma go w
powyższej bazowej konfiguracji — nie dodawaj go, chyba że ustawisz też
opcache.preload.
Zweryfikuj obraz
Dział zatytułowany „Zweryfikuj obraz”Dodaj krok weryfikacji, aby źle zbudowany obraz zawiódł głośno, zamiast wytwarzać tofu
lub błąd krytyczny przy pierwszym żądaniu. NextPDF dostarcza CLI, którego polecenie
doctor inspekcjonuje działające środowisko PHP i raportuje dokładnie te rozszerzenia,
na których silnikowi zależy — openssl, zlib, mbstring, gd, curl oraz intl.
Pakiet deklaruje "bin": ["bin/nextpdf"], więc w aplikacji konsumującej Composer
instaluje plik wykonywalny w vendor/bin/nextpdf (a nie bin/nextpdf, czyli
ścieżce wewnątrz samego pakietu nextpdf/core). Uruchom go wewnątrz zbudowanego
obrazu:
docker run --rm your-app:latest php vendor/bin/nextpdf doctorZdrowy wynik potwierdza, że załadowane są PHP 8.4 i każde wymagane rozszerzenie. Wpnij to samo wywołanie w kompilację (lub zadanie dymne CI), aby brakujące rozszerzenie zatrzymało potok:
# Fail the pipeline if the engine's environment is not healthy.docker run --rm your-app:latest php vendor/bin/nextpdf doctor || exit 1Dla kontroli kompleksowej (end-to-end) wyrenderuj jedną stronę przez swój własny punkt wejścia i sprawdź wyjście, tak jak opisuje strona o czcionkach dla kontroli dymnej czcionek.
Przypadki brzegowe i pułapki
Dział zatytułowany „Przypadki brzegowe i pułapki”php:8.4-fpmlub-apachezamiast-cli. Użyj SAPI, pod którym Twoja aplikacja faktycznie jest obsługiwana. Lista rozszerzeń jest identyczna; różni się tylko tag bazowy orazCMD/punkt wejścia. Dla procesu roboczego kolejki lub wsadowego zadania CLI poprawne jest-cli.- Alpine (
php:8.4-alpine) potrzebuje innych nazw pakietów. Powyższe linieapt-getsą dla domyślnego obrazu opartego na Debianie. Na Alpine zainstaluj nagłówki*-devjako wirtualną grupę kompilacyjną (apk add --no-cache --virtual .build-deps icu-dev libpng-dev freetype-dev libjpeg-turbo-dev oniguruma-dev), a po krokudocker-php-ext-install gd intl mbstring opcacheużyjapk del .build-deps— ale najpierwapk add --no-cachebiblioteki uruchomieniowe, z którymi linkują się rozszerzenia (icu-libs,libpng,freetype,libjpeg-turbo,oniguruma), aby usunięcie grupy kompilacyjnej nie odlinkowałointl.so/gd.so/mbstring.so. To ta sama reguła zachowania bibliotek uruchomieniowych, którą blok Debiana wymusza przezapt-mark. - Nie instaluj pakietów
fonts-*. Są niewidoczne dla natywnego silnika. Zamiast tego dołącz pliki czcionek — zobacz stronę o czcionkach, do której odnosi się powyższy odnośnik. - Premium i ionCube to osobna troska o obraz. Zakodowane przez ionCube kompilacje NextPDF Pro / Enterprise potrzebują Loadera ionCube zainstalowanego w obrazie i dopasowanego do dokładnej kompilacji PHP kontenera (8.4, NTS kontra ZTS). To wykracza poza zakres obrazu rdzenia; jeśli wdrażasz premium, wykonaj kroki z sekcji Docker w Konfiguracja Loadera ionCube.
- Trzymaj hostowy
vendor/poza kontekstem kompilacji. Plik.dockerignore(wykluczającyvendor/,.git/i lokalne pamięci podręczne) całkowicie trzyma drzewo hosta poza kontekstem — to właśnie czyni kompilację małą, szybką i wolną od wycieków lokalnych sekretów. Zabezpiecza też przypadek scalania katalogów:COPYkatalogu to scalenie, a nie zastąpienie, więc zbudowany na hościevendor/, który dotarł do kontekstu, trafiłby tam jako pierwszy, aCOPY --from=vendor /app/vendor /var/www/app/vendornadpisałby tylko te ścieżki, które zawiera czyste drzewo zależności. W tym DockerfileRUN rm -rf /var/www/app/vendorprzed kopią vendor już usuwa dowolny taki katalog, więc ta pozostałość nie może tu wystąpić; ryzyko scalenia wraca tylko wtedy, gdy porzucisz to zabezpieczenierm -rf, dlatego wykluczenie w.dockerignorejest trwałą poprawką.
Uwagi dotyczące bezpieczeństwa
Dział zatytułowany „Uwagi dotyczące bezpieczeństwa”- Nie wysyłaj zależności deweloperskich.
--no-devutrzymuje narzędzia testowe i analizy, a także ich tranzytywne pakiety, poza obrazem uruchomieniowym i jego powierzchnią ataku. - Uruchamiaj nieuprzywilejowanie. Końcowe
USER appuserzapewnia, że żaden proces kontenera nie działa jako root. Połącz to z systemem plików tylko do odczytu oraz odjętymi zdolnościami w Twoim orkiestratorze. - Przypnij obraz bazowy. Przypnij
php:8.4do skrótu (digest) na produkcji, aby przebudowa nie mogła po cichu pobrać zmienionej bazy, i przebudowuj cyklicznie, aby świadomie wprowadzać poprawki bezpieczeństwa. - Trzymaj czcionki i licencje poza publicznymi warstwami. Dołączaj wyłącznie czcionki, które masz prawo osadzić, i nigdy nie wpiekaj pliku licencji premium w publicznie wypchnięty obraz — zamiast tego zamontuj go w czasie działania.
Zgodność
Dział zatytułowany „Zgodność”Ten przewodnik nie zgłasza normatywnego roszczenia co do standardów. Fakty platformowe
są odczytane wprost z pakietu nextpdf/core: ograniczenie php: >=8.4 <9.0 oraz
wymagane rozszerzenia ext-mbstring, ext-intl, ext-gd, ext-openssl, ext-zlib
i ext-curl. Polecenie weryfikacji to prawdziwy handler doctor CLI nextpdf —
zadeklarowany jako "bin": ["bin/nextpdf"] w nextpdf/core, a więc instalowany w
vendor/bin/nextpdf w aplikacji konsumującej — który raportuje ten sam zestaw
rozszerzeń. Natywny silnik rejestruje czcionki przez NextPDF\Typography\FontRegistry
(argument konstruktora katalogu / addFontDirectory()) wpięty przez
NextPDF\Core\DocumentFactory; NEXTPDF_FONTS_PATH to klucz konfiguracji fonts_path
pakietu nextpdf/laravel (env('NEXTPDF_FONTS_PATH', resource_path('fonts'))), a nie
zmienna, którą odczytuje nextpdf/core. Zachowanie rejestru jest udokumentowane na
stronie o czcionkach, do której odnosi się sekcja Zobacz także.
Zobacz także
Dział zatytułowany „Zobacz także”- Udostępnianie czcionek dla natywnego silnika w środowisku produkcyjnym: nazewnictwo plików czcionek, API rejestru oraz wzorzec rozgrzewki-i-zablokowania, na których opiera się ten obraz.
- Strumieniowanie dużego wygenerowanego pliku PDF jako odpowiedzi HTTP: model pamięci do serwowania zbudowanego dokumentu z kontrolera frameworka.
- Renderowanie na brzegu z Cloudflare: gdy kontener działający w ramach procesu nie jest właściwym środowiskiem uruchomieniowym.
- Konfiguracja Loadera ionCube: osobna troska o obraz dla zakodowanych przez ionCube kompilacji premium.