İçeriğe geç
getnextpdf.com

Bir NextPDF uygulamasını kapsayıcılaştırın

Yerel, süreç içi NextPDF çekirdek motorunu — composer require nextpdf/core, PHP sürecinizin içinde PDF üreten — çalıştıran küçük, yeniden üretilebilir bir Docker görüntüsü istiyorsunuz. Bu sayfa tam olarak onu oluşturur: yalnızca motorun gerçekten ihtiyaç duyduğu uzantılarla bir php:8.4 görüntüsü, son katmanda geliştirme bağımlılıkları olmadan, paketlenmiş yazı tipleri, root olmayan bir çalışma zamanı kullanıcısı, üretim için ayarlanmış opcache ve bir şey eksikse derlemeyi başarısız kılan bir doğrulama adımı.

Bu sayfa yalnızca yerel motor içindir. Chrome köprüsü (nextpdf/artisan aracılığıyla writeHtmlChrome) ve Connect sunucusu, kendi daha ağır görüntülerine sahip ayrı çalışma zamanlarıdır — köprü için başsız bir Chromium kurulumu, Connect için uzun ömürlü bir hizmet. Bu görüntüye bir tarayıcı veya bir sunucu eklemeyin; yerel motorun ikisine de ihtiyacı yoktur.

Başlamadan önce, şu parçaların yerinde olduğunu onaylayın:

  • Uygulamanız, bağımlılık olarak nextpdf/core ile birlikte işlenmiş bir composer.json ve composer.lock dosyasına sahiptir.
  • Gömmeyi düşündüğünüz yazı tipi dosyalarına sahipsiniz ve bunları gömme lisansınız var.
  • Uygulama dizininize karşı docker build çalıştırabilirsiniz.

Bu bir işletim nasıl-yapılır kılavuzudur. Burada neredeyse hiç PHP yoktur; iş, Dockerfile ve birkaç ortam ayarıdır.

Görüntü, motorun gerçek platform kısıtlamalarını karşılamalıdır, daha fazlasını değil. Bunları doğrudan paketten okuyarak, nextpdf/core php: >=8.4 <9.0 ve şu PHP uzantılarını gerektirir:

UzantıMotorun ona neden ihtiyaç duyduğu
ext-mbstringMetin ve kodlamalar için çok baytlı dize işleme
ext-intlUnicode, yerel ayar ve uluslararasılaştırma desteği
ext-gdRaster görüntü kod çözme ve işleme
ext-opensslİmzalama ve güvenli özetleme için şifreleme
ext-zlibPDF nesnelerinin akış (Flate) sıkıştırması
ext-curlMotorun giden çağrıları için HTTP istemcisi

Bunları resmi php:8.4 görüntüsüne eşleyin. openssl, curl ve zlib, resmi PHP görüntüsüne zaten derlenmiştir, dolayısıyla onları docker-php-ext-install yapmazsınız. mbstring, gd ve intl paketlenmemiştir ve kurulmalıdır ve her biri önce sistem geliştirme başlıklarının mevcut olmasını gerektirir — mbstring ek olarak libonig-dev (Oniguruma) derleme bağımlılığına ihtiyaç duyar. Paketin listelemediği motor uzantılarını eklemeyin — fazladan her docker-php-ext-install, ihtiyaç duymadığınız derleme süresi ve saldırı yüzeyidir. Bu görüntünün kuracağı tek motor dışı uzantı opcache’dir: bir çalışma zamanı başarım uzantısıdır, resmi görüntüde etkin olarak paketlenmemiştir ve aşağıdaki opcache ayarı onun mevcut olmasına bağlıdır (bkz. “Üretim için opcache”).

Bu iki aşamalı bir derlemedir. İlk aşama, geliştirme paketleri hariç tutularak Composer bağımlılıklarını kurar; ikinci aşama, gönderilen yalın çalışma zamanı görüntüsüdür.

Önce Dockerfile’ın yanına bir .dockerignore ekleyin. Birincil görevi, ana makine ortamını — ana makinede derlenmiş bir vendor/, yerel gizli bilgi dosyaları ve derleme önbellekleri — derleme bağlamından tamamen uzak tutmaktır, böylece COPY . /var/www/app yalnızca amaçladığınızı gönderir: daha küçük, daha hızlı ve yerel .env gizli bilgilerini sızdıramayan ya da ana makinenin megabaytlarca vendor/’ını görüntüye taşımayan daha güvenli derlemeler.

vendor/’ı hariç tutmak ayrıca önemlidir çünkü bir dizin COPY işlemi bir değiştirme değil, bir birleştirmedir. Aşağıdaki Dockerfile, COPY --from=vendor ... /var/www/app/vendor’dan önce RUN rm -rf /var/www/app/vendor çalıştırır, dolayısıyla bu görüntüde bir ana makine vendor/’ı temiz bağımlılık ağacının altında asla hayatta kalamaz. Ancak o rm -rf korumasını kaldırırsanız, bağlamdaki ana makinede derlenmiş bir vendor/ önce iner ve vendor aşaması kopyalaması yalnızca temiz ağacın içerdiği yolların üzerine yazar — fazladan ana makine dosyaları (eski veya dev olarak kurulmuş bir paket, öksüz bir sınıf) o zaman altında hayatta kalır. vendor/’ı bağlamdan uzak tutmak, rm -rf’ten bağımsız olarak o deliği kapatır.

# .dockerignore — keep the host environment out of the build context.
vendor/
.git/
.env
.env.local
.env.*.local
var/cache/
storage/
node_modules/
*.log

Gerçek yerel gizli bilgi dosyalarını (.env, .env.local, .env.*.local) hariç tutun, blanket bir .env.* değil — o joker karakter, görüntünün belgelenmiş bir yapılandırma temeli taşıması için göndermek istediğiniz .env.example gibi gizli olmayan şablonları da düşürür. İşlenmiş, gizli olmayan herhangi bir env şablonunu bağlamda tutun; yalnızca gerçekten yerel gizli bilgileri tutan dosyaları hariç tutun.

# syntax=docker/dockerfile:1
# ---- Stage 1: dependencies (no dev) ---------------------------------------
FROM composer:2 AS vendor
WORKDIR /app
COPY 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/app
RUN rm -rf /var/www/app/vendor
COPY --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/app
USER appuser
CMD ["php", "bin/generate.php"]

Bağımlılık aşaması, eksik bir ağaca karşı hiçbir uygulama kurulum-sonrası kancası çalışmaması için --no-scripts ile çalışır; herhangi bir uygulama derleme adımını (varlık derlemesi, önbellek ısıtma) kod kopyalandıktan sonraki bir aşamada çalıştırın.

Çok aşamalı Composer kurulumu (geliştirme bağımlılıkları yok)

“Çok aşamalı Composer kurulumu (geliştirme bağımlılıkları yok)” başlıklı bölüm

Gönderilen görüntü, geliştirme araçları içermemelidir. composer install üzerindeki --no-dev bayrağı, yük taşıyan satırdır: nextpdf/core ve uygulamanızdaki require-dev altındaki her şeyi — test çalıştırıcısı, statik çözümleyici ve mutasyon araçları — atlar; bunların hiçbirinin üretimde yeri yoktur. Otomatik yükleyicinin her istekte bir dosya sistemi taraması yerine üretilmiş bir sınıf haritası olması için onu --optimize-autoloader ile eşleştirin.

composer.json ve composer.lock dosyalarını kaynağın geri kalanından önce kopyalayın, böylece Docker bağımlılık katmanını önbelleğe alır ve yalnızca lock dosyası değiştiğinde yeniden çözümler. O ilk kurulum yalnızca lock dosyasına karşı — uygulama kaynağı olmadan — çalıştığı için, oradaki --optimize-autoloader sınıf haritasını yalnızca vendor ağacı için oluşturur; uygulamanızın kendi sınıfları henüz mevcut değildir. Bu nedenle çalışma zamanı aşaması, kaynağı kopyaladıktan sonra bir kez composer dump-autoload --optimize --no-dev --no-scripts çalıştırır: uygulamanın sınıflarını aynı en iyileştirilmiş sınıf haritasına katar. Ayrıca geliştirme yaptığınız bir worktree’de ayrı bir composer dump-autoload çalıştırmayın (bu, bir üretim sınıf haritasını bir dev ağacına işler); yeniden oluşturma, yukarıda gösterildiği gibi, kaynak kopyasından sonra, görüntüye aittir.

Yerel motor, yazı tiplerini OS’a kurulu yazı tiplerinden değil, okuyabildiği yazı tipi dosyalarından çözümler. fonts-* paketleri kurmak veya fc-cache çalıştırmak, yerel yolun görebileceği hiçbir şeyi yapmaz, dolayısıyla bu görüntü hiçbir sistem yazı tipi kurmaz. .ttf / .otf dosyalarınızı resources/fonts/ altında paketleyin; yukarıdaki COPY . /var/www/app onları zaten görüntüye taşır.

Dosyaları görüntüye almak işin yalnızca yarısıdır. Yalın yerel motor, hiçbir yazı tipi arama ortam değişkeni okumaz — NEXTPDF_FONTS_PATH, nextpdf/laravel paketinin fonts_path yapılandırma anahtarının varsayılan değeridir (env('NEXTPDF_FONTS_PATH', resource_path('fonts'))) ve yalnızca o çerçeve tümleştirmesi tarafından tüketilir, nextpdf/core tarafından değil. Yalnızca o değişken ayarlı düz bir php bin/generate.php giriş noktası hiçbir yazı tipi kaydetmez ve bu görüntünün önlemek için var olduğu tofunun aynısını işler. Giriş noktası, paketlenmiş dizini PHP’de kaydetmelidir:

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();

Yazı tipleri için tüm Docker kaygısı budur. Dosya adlandırma kuralları, kayıt defteri API’si, ısıtma-ve-kilitleme deseni ve salt okunur dosya sistemi işleme, hepsi özel sayfada bulunur — bunları burada yinelemeyin. Tam desen için Üretimde yerel motor için yazı tiplerini sağlayın sayfasını okuyun ve paketlediğiniz dizinin aynısını kaydedin.

Resmi PHP görüntüleri varsayılan olarak root olarak çalışır. Bir PDF üreticisinin root’a ihtiyacı yoktur, dolayısıyla ayrıcalıksız bir kullanıcı oluşturun ve ona geçin. Yukarıdaki Dockerfile, sabit bir yüksek UID’li (10001) bir sistem kullanıcısı appuser ekler, ona uygulama ağacının sahipliğini verir ve kapsayıcının başlattığı her sürecin ayrıcalıksız olması için USER appuser ile biter.

Yapabildiğiniz yerde uygulamayı çalışma zamanında salt okunur tutun. Motor, yazı tipi dosyalarını okur ve yalnızca çıktısını ve isteğe bağlı bir ayrıştırılmış yazı tipi önbelleğini yazar, dolayısıyla çıktı yolu ve herhangi bir önbellek dizini yazılabilir bağlama olduğu sürece bir readOnlyRootFilesystem kapsayıcısı çalışır. Derinlemesine savunma için bunu düşürülmüş Linux yetenekleriyle ve orkestratörünüzdeki bir no-new-privileges bayrağıyla birleştirin.

Opcache, uzun ömürlü PHP çalışanları için karşılığını verir — tek bir sıcak süreçten birçok isteğe hizmet eden bir FPM havuzu ya da bir Apache mod_php süreci. Bu süreçler sınıflarınızı bir kez derler ve sonra bir sıcak yolda asla kaynak dosyaları stat etmez; opcache.validate_timestamps=0’ın size satın aldığı tam da budur. Opcache, resmi php:8.4 görüntüsünde kutudan çıktığı gibi etkin değildir, dolayısıyla yukarıdaki Dockerfile onu docker-php-ext-install opcache ile kurar (uzantı zaten derlenmişse eşdeğer olarak docker-php-ext-enable opcache yapabilirsiniz). Aşağıdaki conf.d dosyası, etkinleştirme adımı değil, ayardır — uzantı yüklenene kadar hiçbir şey yapmaz. Onu bir conf.d dâhili olarak gönderin (docker/opcache.ini, Dockerfile’da kopyalanmış):

opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=192
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0

opcache.validate_timestamps=0, önbelleğin kaynak dosyaları asla yeniden denetlemediği anlamına gelir — değişmez bir görüntü için doğrudur, çünkü kodun değişmesinin tek yolu yeni bir görüntüdür. memory_consumption ve max_accelerated_files değerlerini uygulamanızın sınıf sayısına göre ayarlayın.

Gösterilen CMD, tek seferlik bir CLI üreticisidir ve opcache.enable_cli=0 bunun için doğrudur. Kısa ömürlü bir php bin/generate.php süreci başlar, derler, bir kez işler ve çıkar, dolayısıyla bir sonraki istekle paylaşamayacağı bir opcode önbelleği hiçbir yarar sağlamaz — CLI opcache’i kapalı bırakın ve bellek maliyetinin hiçbirini ödemeyin. Opcache, yalnızca sürecin yeniden kullanıldığı yerde karşılığını verir: bir FPM/Apache SAPI ya da gerçekten uzun ömürlü bir CLI çalışanı (bir kuyruk tüketicisi veya RoadRunner tarzı bir sunucu). Yalnızca o tür yerleşik bir CLI çalışanı opcache.enable_cli=1 ayarlar; buradaki tek seferlik üretici için onu 0 tutun.

Opcache ön yüklemesi kullanan bir kurulum çalıştırırsanız (bir opcache.preload betiğiyle uzun ömürlü bir FPM çalışanı), opcache.preload=/path/to/preload.php ayarlayın ve ön yüklemenin ayrıcalıksız kullanıcı olarak çalışması için opcache.preload_user=appuser ekleyin. Gerçek bir opcache.preload betiği olmadan, opcache.preload_user hiçbir şey yapmaz, bu nedenle yukarıdaki temel yapılandırmada yer almaz — opcache.preload’u da ayarlamadıkça onu eklemeyin.

Yanlış derlenmiş bir görüntünün ilk istekte tofu veya ölümcül bir hata üretmek yerine yüksek sesle başarısız olması için bir doğrulama adımı ekleyin. NextPDF, doctor komutu çalışan PHP ortamını inceleyen ve motorun önemsediği uzantıların tam olarak hangileri olduğunu — openssl, zlib, mbstring, gd, curl ve intl — bildiren bir CLI gönderir. Paket "bin": ["bin/nextpdf"] bildirir, dolayısıyla onu tüketen bir uygulamada Composer, yürütülebilir dosyayı vendor/bin/nextpdf konumuna kurar (nextpdf/core paketinin kendi içindeki yol olan bin/nextpdf değil). Onu derlenen görüntünün içinde çalıştırın:

Terminal window
docker run --rm your-app:latest php vendor/bin/nextpdf doctor

Sağlıklı bir sonuç, PHP 8.4 ve gereken her uzantının yüklü olduğunu onaylar. Eksik bir uzantının işlem hattını durdurması için aynı çağrıyı derlemeye (veya bir CI duman işine) bağlayın:

Terminal window
# Fail the pipeline if the engine's environment is not healthy.
docker run --rm your-app:latest php vendor/bin/nextpdf doctor || exit 1

Uçtan uca bir denetim için, kendi giriş noktanız aracılığıyla bir sayfa işleyin ve yazı tipleri sayfasının bir yazı tipi duman denetimi için tarif ettiği gibi çıktı üzerinde bir ifade kurun.

  • -cli yerine php:8.4-fpm veya -apache. Uygulamanızın gerçekten hizmet verdiği SAPI’yi kullanın. Uzantı listesi aynıdır; yalnızca temel etiket ve CMD/giriş noktası farklıdır. Bir kuyruk çalışanı veya bir CLI toplu işi için -cli doğrudur.
  • Alpine (php:8.4-alpine) farklı paket adlarına ihtiyaç duyar. Yukarıdaki apt-get satırları Debian tabanlı varsayılan görüntü içindir. Alpine’de, *-dev başlıklarını sanal bir derleme grubu olarak kurun (apk add --no-cache --virtual .build-deps icu-dev libpng-dev freetype-dev libjpeg-turbo-dev oniguruma-dev) ve docker-php-ext-install gd intl mbstring opcache adımından sonra apk del .build-deps yapın — ancak önce uzantıların bağlandığı çalışma zamanı kitaplıklarını apk add --no-cache ile ekleyin (icu-libs, libpng, freetype, libjpeg-turbo, oniguruma), böylece derleme grubunu silmek intl.so / gd.so / mbstring.so bağlantısını kesmez. Bu, Debian bloğunun apt-mark ile zorladığı aynı çalışma-zamanı-kitaplıklarını-koru kuralıdır.
  • fonts-* paketleri kurmayın. Bunlar yerel motora görünmezdir. Bunun yerine yazı tipi dosyalarını paketleyin — yukarıda bağlantısı verilen yazı tipleri sayfasına bakın.
  • Premium ve ionCube, farklı bir görüntü kaygısıdır. ionCube ile kodlanmış NextPDF Pro / Enterprise derlemeleri, görüntüye kurulmuş ve kapsayıcının tam PHP derlemesine (8.4, NTS ve ZTS) eşlenmiş ionCube Loader’a ihtiyaç duyar. Bu, bir çekirdek görüntüsü için kapsam dışıdır; premium dağıtıyorsanız, ionCube Loader kurulumu sayfasının Docker bölümünü izleyin.
  • Bir ana makine vendor/’ını derleme bağlamından uzak tutun. .dockerignore (vendor/, .git/ ve yerel önbellekleri hariç tutarak) ana makine ağacını bağlamdan tamamen uzak tutar — derlemeyi küçük, hızlı ve sızdırılmış yerel gizli bilgilerden arınmış kılan budur. Ayrıca dizin-birleştirme durumunu korur: bir dizin COPY bir değiştirme değil, bir birleştirmedir, dolayısıyla bağlama ulaşan ana makinede derlenmiş bir vendor/ önce iner ve COPY --from=vendor /app/vendor /var/www/app/vendor yalnızca temiz bağımlılık ağacının içerdiği yolların üzerine yazar. Bu Dockerfile’da, vendor kopyasından önceki RUN rm -rf /var/www/app/vendor böyle bir dizini zaten kaldırır, dolayısıyla o kalıntı burada oluşamaz; birleştirme riski yalnızca o rm -rf korumasını düşürürseniz geri döner, bu nedenle .dockerignore hariç tutması kalıcı düzeltmedir.
  • Hiçbir geliştirme bağımlılığı göndermeyin. --no-dev, test ve çözümleme araçlarını ve onların geçişli paketlerini çalışma zamanı görüntüsünden ve saldırı yüzeyinden uzak tutar.
  • Ayrıcalıksız çalıştırın. Son USER appuser, hiçbir kapsayıcı sürecinin root olarak çalışmamasını sağlar. Onu salt okunur bir kök dosya sistemi ve orkestratörünüzdeki düşürülmüş yeteneklerle eşleştirin.
  • Temel görüntüyü sabitleyin. Bir yeniden derlemenin değişmiş bir temeli sessizce çekememesi için üretimde php:8.4’ü bir özete sabitleyin ve güvenlik yamalarını bilinçli olarak almak üzere bir ritimde yeniden derleyin.
  • Yazı tiplerini ve lisansları herkese açık katmanlardan uzak tutun. Yalnızca gömme lisansınız olan yazı tiplerini paketleyin ve herkese açık olarak gönderilen bir görüntüye asla bir premium lisans dosyası gömmeyin — onu bunun yerine çalışma zamanında bağlayın.

Bu kılavuz normatif bir standart iddiasında bulunmaz. Platform olguları doğrudan nextpdf/core paketinden okunur: php: >=8.4 <9.0 kısıtlaması ve gereken uzantılar ext-mbstring, ext-intl, ext-gd, ext-openssl, ext-zlib ve ext-curl. Doğrulama komutu, aynı uzantı kümesini bildiren gerçek nextpdf CLI doctor işleyicisidir — nextpdf/core içinde "bin": ["bin/nextpdf"] olarak bildirilir ve dolayısıyla onu tüketen bir uygulamada vendor/bin/nextpdf konumuna kurulur. Yerel motor, yazı tiplerini NextPDF\Core\DocumentFactory aracılığıyla bağlanmış NextPDF\Typography\FontRegistry (dizin yapıcı argümanı / addFontDirectory()) üzerinden kaydeder; NEXTPDF_FONTS_PATH, nextpdf/laravel paketinin fonts_path yapılandırma anahtarıdır (env('NEXTPDF_FONTS_PATH', resource_path('fonts'))), nextpdf/core’un okuduğu bir değişken değil. Kayıt defteri davranışı, Ayrıca bakınız altında bağlantısı verilen yazı tipleri sayfasında belgelenmiştir.