Lambda上でPuppeteer/Headless Chromeを動かすStarter Kitを作った

node.jswebawsproduct

PuppeteerでHeadless Chromeを動かすコードを Lambda上で動かすStarter Kitを作った。

puppeteer-lambda-starter-kit

Chromeの準備

Puppeteerのインストール時に落としてくるChromeをLambda上で動かそうとしても Lambdaにないshared libraryに依存しているため失敗する。

error while loading shared libraries: libpangocairo-1.0.so.0: cannot open shared object file: No such file or directory

Lambda上でHeadless Chromeを動かす例がないか調べたらserverless-chromeというのがあって、 Headless用の設定でChromeをビルドしていた。 ほかにはchromelessというのもあるが これはserverless-chromeに 依存している。 最小構成でPuppeteerを使いたかったので、今回はこれらを使わず一から作ることにした。

serverless-chromeにもビルドしたものが置いてあるが、少しバージョンが古いようだったので最新版でビルドした。 基本的には書いてある 通りやればうまくいく。他のプロセスとのshared memoryとして/dev/shmを使っているのを、/tmpに置き換える ようにしないと、実行時の page.goto() で Failed Provisional Load: ***, error_code: -12 になる。

ビルドしたheadless_shellには問題になった依存は含まれていないようだ。

$ ldd headless_shell 
	linux-vdso.so.1 =>  (0x00007ffcb6fed000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f5f17dbe000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f5f17bba000)
	librt.so.1 => /lib64/librt.so.1 (0x00007f5f179b1000)
	libnss3.so => /usr/lib64/libnss3.so (0x00007f5f17692000)
	libnssutil3.so => /usr/lib64/libnssutil3.so (0x00007f5f17466000)
	libsmime3.so => /usr/lib64/libsmime3.so (0x00007f5f1723e000)
	libnspr4.so => /lib64/libnspr4.so (0x00007f5f17001000)
	libexpat.so.1 => /lib64/libexpat.so.1 (0x00007f5f16dd8000)
	libfontconfig.so.1 => not found
	libfreetype.so.6 => /usr/lib64/libfreetype.so.6 (0x00007f5f16b3b000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f5f16839000)
	libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f5f16533000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f5f1631d000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f5f15f5b000)
	/lib64/ld-linux-x86-64.so.2 (0x000055ba0af5e000)
	libplc4.so => /lib64/libplc4.so (0x00007f5f15d55000)
	libplds4.so => /lib64/libplds4.so (0x00007f5f15b51000)

Puppetterで落としてくる普通のChromeはLambdaの制限の50MBを超えていたが、 ビルドしたものはぎりぎり超えていないのでパッケージに含められるようになった。 PuppeteerのChromeは環境変数 PUPPETEER_SKIP_CHROMIUM_DOWNLOAD を設定することで含めないようにできる

他のパッケージのサイズによっては50MBを超えてしまうこともあるので、 パッケージに含めずS3からダウンロードできるようにもした。

いずれの場合も最終的な置き先はLambdaで唯一書き込める/tmpになる。 この領域は512MBまで使えるので展開してもまだ余裕がある。

Error: EROFS: read-only file system, open 'node_modules/puppeteer/.local-chromium'

ChromeのLaunch時のOption

いろいろ試した結果、最低限必要だったのはこのあたり。

exports.launchOptionForLambda = [
    // error when launch(); No usable sandbox! Update your kernel
    '--no-sandbox',
    // error when launch(); Failed to load libosmesa.so
    '--disable-gpu', 
    // freeze when newPage()
    '--single-process'
];

エラーは分かりづらいものが多く、ときにはエラーすら出ずに止まってしまうこともある。 デバッグの際はdumpioを有効にする。

const browser = await puppeteer.launch({
    ...
    dumpio: !!util.DEBUG,
});  

Babel

現在のLambdaのNodeのバージョンはv6.10.3。 node.greenによるとES2015は99%対応していて、ES2016もべき乗演算子(2 ** 3 = 8)以外は対応しているが、ES2017のasync/awaitは7.6からなので、8系に対応するまではbabelにかける必要がある。 ちなみにPuppeteerは6.4以降で動く

$ yarn add --dev babel-cli babel-preset-env

babel-preset-env .babelrcはこんな感じ。

$ cat .babelrc
{
  "presets": [
    ["env", {
      "targets": {
        "node": "6.10"
      }
    }]
  ]
}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy