Docker

Debian / Ubuntu の apt install wkhtmltopdf で入る wkhtmltopdf は「unpatched qt」版で、--footer-center などのフッター・ヘッダー指定を無視し、ローカルのCSSや画像も file:// では読みません。PDFのページ番号が消える、スタイルが当たらない、という症状はこの2点が原因です。公式配布の「patched qt」版の .deb を入れ、0.12.6以降ではローカルファイルの読み込みを明示的に許可すれば直ります。

症状からunpatched qtだと判定する

wkhtmltopdf の標準エラー出力に、次のどちらかが出ていればこの記事の対象です。

The switch --footer-center, is not support using unpatched qt, and will be ignored.
Blocked access to file /path/to/app/assets/css/style.css

1つ目はフッター・ヘッダー・目次など「Qtに手を入れないと実装できない」オプションを使ったときに出ます。エラーにはならず、警告だけ出してPDFは生成されるので、ページ番号が無いPDFを見て初めて気付きます。2つ目は 0.12.6 で入った既定の制限で、HTMLから file:// で参照したCSS・画像・フォントを読まなくなりました。こちらも警告だけでPDF自体は出ます。

入っている版がどちらかは wkhtmltopdf --version で分かります。apt版は wkhtmltopdf 0.12.6 (unpatched qt) のように、公式版は (with patched qt) と表示されます。

Dockerfileで公式の.debを入れる

公式版は wkhtmltopdf/packaging でOSごとに .deb が配布されています。php:8.2-fpm-bookworm に入れる場合の例です。

RUN apt-get update && apt-get install -y --no-install-recommends \
        fontconfig libfontconfig1 libx11-6 libxcb1 libxrender1 libxext6 libjpeg62-turbo \
        xfonts-75dpi xfonts-base fonts-ipafont-gothic fonts-ipafont-mincho \
    && rm -rf /var/lib/apt/lists/*

RUN set -eux; \
    arch="$(dpkg --print-architecture)"; \
    curl -fsSL -o /tmp/wkhtmltox.deb \
      "https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.bookworm_${arch}.deb"; \
    dpkg -i /tmp/wkhtmltox.deb; \
    rm -f /tmp/wkhtmltox.deb; \
    /usr/local/bin/wkhtmltopdf --version

依存パッケージを先に入れるのが要点です。.deb は依存を自動解決しないので、最初に依存なしで dpkg -i したビルドは次のエラーで止まりました。

dpkg: dependency problems prevent configuration of wkhtmltox:
 wkhtmltox depends on fontconfig; however:
  Package fontconfig is not installed.

上のリストは 0.12.6.1-3 の bookworm 版が要求する依存と、日本語PDFに必要なフォント(IPAフォント)をまとめたものです。dpkg --print-architecture で amd64 / arm64 を切り替えているので、Apple Silicon のMacで作ったイメージも x86_64 のサーバーでも同じDockerfileで動きます。最後の --version はビルド時の動作確認で、ここで (with patched qt) と出れば、フッターが使える版が入っています。公式版は /usr/local/bin に入るので、apt版を /usr/bin に残していると呼び分けを間違えます。apt版は入れないでください。

ローカルファイルの読み込みを許可する

0.12.6以降は patched qt 版でも file:// の参照は既定で拒否されます。コマンドラインなら --enable-local-file-access を付けます。

wkhtmltopdf --enable-local-file-access --footer-center '[page] / [topage]' input.html output.pdf

PHPから knp-snappy 経由で呼んでいる場合は、オプションを設定に持たせます。

# knp_snappy.yaml
knp_snappy:
    pdf:
        enabled: true
        binary: '%env(WKHTMLTOPDF_PATH)%'
        options:
            enable-local-file-access: true

この許可は「HTML内で file:// 参照しているものを読む」だけで、HTTP経由の参照には関係ありません。CSSをHTMLにインライン展開しているなら不要です。

直ったことの確認はPDFではなく標準エラーで見る

生成されたPDFを目で見て確認するより、標準エラーに will be ignoredBlocked access to file が出ていないことを確認する方が確実です。フッターは全ページに出るとは限らず、CSSの欠落も見落としやすいためです。2つの警告が消えたうえで、ページ番号とスタイルが載ったPDFが出ていれば完了です。