wkhtmltopdfを外部サーバーに置いてスケーリングする

wkhtmltopdfを外部サーバーに置いてスケーリングする

HTMLをPDFに変換するライブラリでお馴染みのwkhtmltopdfを外部サーバーに配置して使用する方法です。

外部サーバーに置く

PDF生成処理は重いです。
特にページ数が何ページもあったり、画像を含めば含むほど重くなります。

PDF生成を滅多に行わないアプリケーションであれば、別サーバーに分けることなくアプリケーションサーバーにwkhtmltopdfを同居しても構いませんが、PDF生成で負荷が掛かる場合はPDF生成負荷=アプリケーションサーバー負荷に直結してしまうので分けたほうがいいでしょう。

Dockerコンテナで環境構築する

dockerコンテナですぐに使い始められるようにイメージにしてdocker-hubに配布されています。
GitHubのページはtraum-ferienwohnungen/docker-wkhtmltopdf-aasで、元々配布されていたものがForkされたリポジトリになります。
本家のリポジトリは既にメンテナンスされていません。

docker-composeでPHPコンテナとPDFコンテナを作る方法を例に記載していきます。

docker-compose.yml

version: "3"

services:
  pdf:
    image: "traumfewo/docker-wkhtmltopdf-aas"
    args:
      - USER:${PDF_USER}
      - PASS:${PDF_PASS}
    ports:
      - 5555:5555
    networks:
      - sample_network
  
  php:
    image: php
    networks:
      - sample_network
  
networks:
  sample_network:
    external: true

 

コンテナ間の通信を可能にするために2つのコンテナはsample_netowkに属しています。
ネットワークは事前に作成しておきましょう。

docker network create sample_network

.env

PDF_USER=goduser
PDF_PASS=secretpassword

 

BASIC認証のIDやパスワードは直接記述するとセキュリティリスクなので.envに記載します。

ホストから実行する

docker-compose up -d --buildから定義ファイルを元にコンテナを開始します。
ホストのコンソールから以下のコマンドを入力することでPDFコンテナにリクエストしてPDFを生成できます。

content=$(echo "<html>Your HTML content</html>" | base64)
footer=$(echo "<html>Your HTML footer</html>" | base64)
curl -vvv -H "Content-Type: application/json" -X POST -d \
    '{"contents": "'"$content"'",
      "options": {
        "margin-top": "20",
        "margin-left": "20",
        "margin-right": "20",
        "margin-bottom": "30"
      },
      "footer": "'"$footer"'"}' \
http://goduser:secretpassword@localhost:5555 -o OUTPUT_NAME.pdf

 

実行したカレントディレクトリにOUTPUT_NAME.pdfファイルが保存されます。

別コンテナから実行する

docker-compose exec php bashでPHPコンテナに入ります。
コンソールから以下のコマンドでPHPコンテナからPDFコンテナへPDF生成をリクエストできます。

content=$(echo "<html>Your HTML content</html>" | base64)
footer=$(echo "<html>Your HTML footer</html>" | base64)
curl -vvv -H "Content-Type: application/json" -X POST -d \
    '{"contents": "'"$content"'",
      "options": {
        "margin-top": "20",
        "margin-left": "20",
        "margin-right": "20",
        "margin-bottom": "30"
      },
      "footer": "'"$footer"'"}' \
http://goduser:secretpassword@pdf -o OUTPUT_NAME.pdf

 

ポイントはリクエスト先のホスト名がlocalhost:[port]ではなくコンテナ間なので相手のコンテナ名pdfになります。

認証のID・パスワードは実際の値に置き換えて下さい
暗号化必須のため本番環境はhttps必須です

あとは任意の言語からリクエストを投げる

PHPならcurlやguzzle、PythonならRequestsなど、各言語のHTTPクライアントからリクエストを投げてやればOKです。
サンプルコードはGitHub等にも載っているので参考にしましょう。

豆知識

AWSのlambda等のサーバーレスで実行可能な環境へwkhtmltopdfを配置することも可能です。
細かい設定が少々手間ですが、構築さえしてしまえばスケーリングは勝手にやってくれるので保守は楽ちんです。

また、wkhtmltopdfは日本語フォントが入っていないので日本語を含む場合は別途設定が必要です。

プログラミングカテゴリの最新記事