Docker設定
Docker内でArtisanを実行するには、コンテナにChromeまたはChromiumバイナリが必要です。このガイドでは、本番環境対応のDockerfileパターン、Compose設定、セキュリティの考慮事項、フォントサポートについて説明します。
Dockerfile
最小構成(Debianベース)
FROM php:8.3-cli
# Chromiumと必要なライブラリをインストール
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/*
# Artisan自動検出用のChromeパスを設定
ENV CHROME_PATH=/usr/bin/chromium
# Composer依存関係をインストール
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader
COPY . .Alpineベース(よりコンパクトなイメージ)
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
services:
app:
build: .
volumes:
- ./output:/app/output
environment:
CHROME_PATH: /usr/bin/chromium
deploy:
resources:
limits:
memory: 1G
reservations:
memory: 512M
# DockerでのChromeサンドボックスに必要
security_opt:
- seccomp=unconfined
cap_add:
- SYS_ADMINDocker向けChromeフラグ
コンテナ内のChromeを確実に動作させるには特定のフラグが必要です。レンダラー作成時にフラグを渡してください。
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
$renderer = HtmlRenderer::create(
chromeFlags: [
'--no-sandbox', // seccompを設定しない場合は必須
'--disable-setuid-sandbox', // セカンダリサンドボックスのバイパス
'--disable-gpu', // コンテナにGPUなし
'--disable-dev-shm-usage', // /dev/shmの代わりに/tmpに書き込み
'--disable-software-rasterizer',
'--single-process', // シンプルなレンダリングではメモリを削減
],
);WARNING
--no-sandbox フラグはChromeのプロセスサンドボックスを無効にします。本番環境では、サンドボックスを有効にしたまま、コンテナに SYS_ADMIN ケーパビリティを付与するか、カスタムseccompプロファイルを使用することを推奨します。
セキュリティの考慮事項
オプションA:サンドボックスを維持(推奨)
コンテナに SYS_ADMIN を追加し、--no-sandbox を省略します。
services:
app:
cap_add:
- SYS_ADMIN
security_opt:
- seccomp=chrome-seccomp.jsonChromeの最小seccompプロファイルはChromiumプロジェクトのドキュメントで入手できます。
オプションB:非rootユーザー
コンテナ内で専用の非特権ユーザーとしてChromeを実行します。
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:読み取り専用ファイルシステム
ルートファイルシステムを読み取り専用でマウントし、Chrome用に書き込み可能なtmpfsを提供します。
services:
app:
read_only: true
tmpfs:
- /tmp
- /home/artisan/.configメモリ制限
Chromeは、特に複雑なページをレンダリングする際にかなりのメモリを消費する可能性があります。コンテナの制限を設定し、使用量を監視してください。
| ページの複雑さ | 推奨メモリ |
|---|---|
| シンプルなテキスト(1〜5ページ) | 256 MB |
| テーブルと画像(5〜20ページ) | 512 MB |
| 複雑なレイアウト、チャート、JS(20ページ以上) | 1 GB以上 |
Chromeがメモリ不足になると、コード137(OOM killed)で終了します。Artisanの RenderException が説明的なメッセージでこれをラップします。
// メモリの暴走を避けるためにタイトなタイムアウトで早期失敗
$options = RenderOptions::create()->setTimeout(15000);フォントのインストール
Dockerイメージには最小限のフォントしか含まれていません。非ラテン文字やブランドタイポグラフィの適切なレンダリングのために、追加フォントをインストールしてください。
システムフォント
# CJKフォント(中国語、日本語、韓国語)
RUN apt-get update && apt-get install -y \
fonts-noto-cjk \
fonts-noto-cjk-extra
# アラビア語、ヘブライ語、デーヴァナーガリー
RUN apt-get install -y \
fonts-noto-core \
fonts-noto-extra
# Google Fonts(例:Inter、Roboto)
RUN apt-get install -y fonts-interカスタムフォント
フォントファイルをコンテナにコピーし、fontconfigに登録します。
COPY ./fonts/*.ttf /usr/share/fonts/custom/
RUN fc-cache -fvWebフォント
ArtisanのChromeは、通常のブラウザと同様にレンダリング時に @font-face Webフォントを取得できます。追加の設定は不要ですが、コンテナからフォントCDNへのネットワークアクセスがあることを確認してください。
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
body {
font-family: 'Inter', sans-serif;
}ヘルスチェック
Chromeが動作可能であることを確認するヘルスチェックを追加します。
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本番環境向け完全な例
FROM php:8.3-cli-bookworm AS base
# システム依存関係 + 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
# 非rootユーザー
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"]