PuppeteerでHTML→PDF変換 on Cloud Run
この記事について
この記事ではPuppeteerを使ってHTMLをPDFに変換するAPIをCloud Run上に構築する方法について紹介します。関連リソースを下記に示します。
おおまかな流れ
おおまかな流れを下記に示します。
- コーディングの準備
- コーディング
- ローカルでの動作確認
- Dockerfileの作成
- コンテナイメージのビルド
- コンテナでの動作確認
- Cloud Runへのデプロイ
- Cloud Runでの動作確認
- 後片付け
コーディングの準備
下記のコマンドを実行してコーディングの準備をします。
npm init -y
npm install --save dotenv express puppeteer
touch .dockerignore .env api-render.mjs Dockerfile main.mjs test.html
コーディング
エディタで下記のファイルを開いて内容を入力します。
main.mjs
api-render.mjs
ポイントを下記に示します。
- Puppeteerの起動オプションに--no-sandboxを指定します。--no-sandboxは指定しない方が望ましいですが、コンテナを起動する時に--cap-add=SYS_ADMINが必要になるのでCloud Runで実行できなくなくなります。
- page.setContentのwaitUntilオプションに'networkidle0'を指定します。これにより、Webフォントなどの読み込みを待機することができます。
.env
ローカルでの動作確認
下記のコマンドを実行してサーバーを起動します。
node -r dotenv/config main.mjs
エディタでtest.htmlを開いて下記の内容を入力します。
下記のコマンドを実行してtest.htmlをtest.pdfに変換します。
cat test.html | curl http://localhost:3000/api/render -X POST --data-binary @- -v > test.pdf
test.pdfを開いて内容を確認します。
Dockerfileの作成
エディタで下記のファイルを開いて内容を入力します。
Dockerfile
Dockerfileの内容については下記2点の合わせ技です。
なお、Webフォントを利用する場合は下記のパッケージをインストールしないことで約50MBほどコンテナイメージのサイズを削減することができます。
- fonts-ipafont-gothic
- fonts-wqy-zenhei
- fonts-thai-tlwg
- fonts-kacst
- fonts-freefont-ttf
.dockerignore
コンテナイメージのビルド
下記のコマンドを実行してコンテナイメージをビルドします。
docker image build -t puppeteer-html2pdf .
出力結果を下記に示します。
[+] Building 6.8s (11/11) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 743B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 34B 0.0s
=> [internal] load metadata for docker.io/library/node:lts-slim 2.4s
=> [1/6] FROM docker.io/library/node:lts-slim@sha256:297b6dbff6c1643db17 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 13.88kB 0.0s
=> CACHED [2/6] RUN apt-get update && apt-get install -y wget gnupg 0.0s
=> CACHED [3/6] WORKDIR /usr/src/app 0.0s
=> [4/6] COPY package*.json ./ 0.0s
=> [5/6] RUN npm ci --only=production 3.9s
=> [6/6] COPY . . 0.0s
=> exporting to image 0.3s
=> => exporting layers 0.3s
=> => writing image sha256:45ea456be2d971c2ae97cbf155aac0fb7f0cee5118c21 0.0s
=> => naming to docker.io/library/puppeteer-html2pdf 0.0s
コンテナでの動作確認
下記のコマンドを実行してコンテナを起動します。
docker container run --init -it --rm \
--name puppeteer-html2pdf \
--env PORT=3000 \
--env PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable \
-p 3000:3000 \
puppeteer-html2pdf
下記のコマンドを実行してtest.htmlをtest.pdfに変換します。なお、コマンドの内容はローカルでの動作確認時と同じです。
cat test.html | curl http://localhost:3000/api/render -X POST --data-binary @- -v > test.pdf
Cloud Runへのデプロイ
下記のコマンドを実行してCloud Runへデプロイします。
IMAGE=asia-northeast1-docker.pkg.dev/`gcloud config get-value project`/cloud-run/puppeteer-html2pdf
# Artifact Registryにプッシュするためにタグ付けします
docker tag puppeteer-html2pdf ${IMAGE}
# Artifact Registryにコンテナイメージをプッシュします
docker push ${IMAGE}
# Cloud Runにコンテナイメージをデプロイします
gcloud run deploy puppeteer-html2pdf \
--image ${IMAGE} \
--region asia-northeast1 \
--platform managed \
--allow-unauthenticated \
--set-env-vars "PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable"
Cloud Runでの動作確認
下記のコマンドを実行してtest.htmlをtest.pdfに変換します。なお、コマンドの内容はURLを除いてローカルおよびコンテナでの動作確認時と同じです。
cat test.html | curl https://puppeteer-html2pdf-xxxxxxxxxx-an.a.run.app/api/render -X POST --data-binary @- -v > test.pdf
後片付け
下記のコマンドを実行してCloud Runへデプロイしたサービスを削除します。
gcloud run services delete puppeteer-html2pdf \
--region asia-northeast1 \
--platform managed
おわりに
現在のままでは誰でもAPIにアクセスできる状態なので、アクセスを制限するにはBasic認証やOAuthを設定することが望ましいです。設定方法については関連記事で紹介しているので必要に応じてご参照ください。
Discussion