Skip to content

Настройка Docker

Запуск Artisan внутри Docker требует наличия бинарного файла Chrome или Chromium в контейнере. Это руководство охватывает продакшен-готовые паттерны Dockerfile, конфигурацию Compose, аспекты безопасности и поддержку шрифтов.

Dockerfile

Минимальный (на основе Debian)

dockerfile
FROM php:8.3-cli

# Install Chromium and required libraries
RUN apt-get update && apt-get install -y --no-install-recommends \
    chromium \
    fonts-liberation \
    libappindicator3-1 \
    libasound2 \
    libatk-bridge2.0-0 \
    libatk1.0-0 \
    libcups2 \
    libdbus-1-3 \
    libdrm2 \
    libgbm1 \
    libnspr4 \
    libnss3 \
    libx11-xcb1 \
    libxcomposite1 \
    libxdamage1 \
    libxrandr2 \
    xdg-utils \
    && rm -rf /var/lib/apt/lists/*

# Set Chrome path for Artisan auto-detection
ENV CHROME_PATH=/usr/bin/chromium

# Install Composer dependencies
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader

COPY . .

На основе Alpine (меньший образ)

dockerfile
FROM php:8.3-cli-alpine

RUN apk add --no-cache \
    chromium \
    nss \
    freetype \
    harfbuzz \
    ca-certificates \
    ttf-freefont \
    font-noto-cjk

ENV CHROME_PATH=/usr/bin/chromium-browser

COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader

COPY . .

Docker Compose

yaml
services:
  app:
    build: .
    volumes:
      - ./output:/app/output
    environment:
      CHROME_PATH: /usr/bin/chromium
    deploy:
      resources:
        limits:
          memory: 1G
        reservations:
          memory: 512M
    # Required for Chrome sandboxing in Docker
    security_opt:
      - seccomp=unconfined
    cap_add:
      - SYS_ADMIN

Флаги Chrome для Docker

Chrome в контейнере требует специфических флагов для надёжной работы. Передайте их при создании рендерера.

php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;

$renderer = HtmlRenderer::create(
    chromeFlags: [
        '--no-sandbox',              // required unless you configure seccomp
        '--disable-setuid-sandbox',  // secondary sandbox bypass
        '--disable-gpu',             // no GPU in containers
        '--disable-dev-shm-usage',   // write to /tmp instead of /dev/shm
        '--disable-software-rasterizer',
        '--single-process',          // reduce memory for simple renders
    ],
);

WARNING

Флаг --no-sandbox отключает процессную песочницу Chrome. В продакшене предпочтительнее сохранять песочницу включённой и предоставить контейнеру capability SYS_ADMIN или использовать пользовательский seccomp-профиль.

Аспекты безопасности

Вариант A: Сохранить песочницу (рекомендуется)

Добавьте SYS_ADMIN контейнеру и не используйте --no-sandbox.

yaml
services:
  app:
    cap_add:
      - SYS_ADMIN
    security_opt:
      - seccomp=chrome-seccomp.json

Минимальный seccomp-профиль для Chrome можно найти в документации проекта Chromium.

Вариант B: Непривилегированный пользователь

Запускайте Chrome от имени выделенного непривилегированного пользователя внутри контейнера.

dockerfile
RUN groupadd -r artisan && useradd -r -g artisan -G audio,video artisan \
    && mkdir -p /home/artisan/Downloads \
    && chown -R artisan:artisan /home/artisan

USER artisan

Вариант C: Файловая система только для чтения

Смонтируйте корневую файловую систему как read-only и предоставьте записываемый tmpfs для Chrome.

yaml
services:
  app:
    read_only: true
    tmpfs:
      - /tmp
      - /home/artisan/.config

Лимиты памяти

Chrome может потреблять значительный объём памяти, особенно при рендеринге сложных страниц. Установите лимиты контейнера и отслеживайте использование.

Сложность страницыРекомендуемая память
Простой текст (1--5 страниц)256 МБ
Таблицы и изображения (5--20 страниц)512 МБ
Сложные макеты, графики, JS (20+ страниц)1 ГБ+

Если Chrome исчерпает память, он завершается с кодом 137 (OOM killed). RenderException в Artisan оборачивает это с описательным сообщением.

php
// Fail fast with a tight timeout to avoid memory runaway
$options = RenderOptions::create()->setTimeout(15000);

Установка шрифтов

Docker-образы поставляются с минимальным набором шрифтов. Установите дополнительные шрифты для правильного рендеринга нелатинских скриптов и брендовой типографики.

Системные шрифты

dockerfile
# CJK fonts (Chinese, Japanese, Korean)
RUN apt-get update && apt-get install -y \
    fonts-noto-cjk \
    fonts-noto-cjk-extra

# Arabic, Hebrew, Devanagari
RUN apt-get install -y \
    fonts-noto-core \
    fonts-noto-extra

# Google Fonts (e.g., Inter, Roboto)
RUN apt-get install -y fonts-inter

Пользовательские шрифты

Скопируйте файлы шрифтов в контейнер и зарегистрируйте их через fontconfig.

dockerfile
COPY ./fonts/*.ttf /usr/share/fonts/custom/
RUN fc-cache -fv

Веб-шрифты

Chrome в Artisan может загружать @font-face веб-шрифты во время рендеринга, как обычный браузер. Дополнительная настройка не требуется, но убедитесь, что контейнер имеет сетевой доступ к CDN шрифтов.

css
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');

body {
    font-family: 'Inter', sans-serif;
}

Проверка работоспособности

Добавьте health check, проверяющий работоспособность Chrome.

dockerfile
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
    CMD chromium --headless=new --disable-gpu --no-sandbox \
        --dump-dom about:blank > /dev/null 2>&1 || exit 1

Полный продакшен-пример

dockerfile
FROM php:8.3-cli-bookworm AS base

# System dependencies + Chromium
RUN apt-get update && apt-get install -y --no-install-recommends \
    chromium \
    fonts-liberation \
    fonts-noto-cjk \
    libnss3 libgbm1 libatk-bridge2.0-0 \
    && rm -rf /var/lib/apt/lists/*

ENV CHROME_PATH=/usr/bin/chromium

# Non-root user
RUN groupadd -r artisan && useradd -r -g artisan artisan \
    && mkdir -p /home/artisan && chown artisan:artisan /home/artisan

WORKDIR /app

COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader

COPY --chown=artisan:artisan . .

USER artisan

HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
    CMD chromium --headless=new --no-sandbox --dump-dom about:blank > /dev/null 2>&1

CMD ["php", "artisan", "render:process"]

Далее

Распространяется по лицензии LGPL-3.0-or-later.