理系学生日記

おまえはいつまで学生気分なのか

Puppetterを使ったアプリをコンテナ化してLambdaにデプロイする

ChromeやChromiumをNode.jsから操作できるライブラリとしてPuppetterがあります。

これを使うと、Chromeでできるさまざまな事柄が自動化できます。

一方で、PuppetterはChromeを内蔵しており、Lambda関数化したとしてもそのサイズは非常に大きくなります。 Lambdaのパッケージサイズ制限は以下の通り(Lambda quotas)であり、通常Lambda関数化できません。

  • 50 MB (zipped, for direct upload)
  • 250 MB (unzipped)
  • 3 MB (console editor)

この問題を解決するために、AWS Lambda用の別ライブラリも存在しています。

ただ、Lambda関数をコンテナ化すると、そのサイズ制限は10GBとなり、自由度が大きくなります。

Container image code package size: 10 GB

それであれば、Puppetterを組み込んだアプリをコンテナ化すれば良いのでは?という発想に至りました。

アプリ

例えば以下のようなコードを作ります。 Lambda関数として構成するので、exports.handlerを定義します。 launchargsにはさまざまな初期化オプションを与えていますが、 これはAWS LambdaがコンテナイメージをサポートしたのでPuppeteerしてみたを参考にさせていただきました。

コマンドラインスイッチについてはList of Chromium Command Line Switchesあたりを参照。

const puppeteer = require("puppeteer");

exports.handler = async (event, context, callback) => {
    const browser = await puppeteer.launch({
        headless: true,
        args: [
            "--no-sandbox",
            "--disable-setuid-sandbox",
            "-–disable-dev-shm-usage",
            "--disable-gpu",
            "--no-first-run",
            "--no-zygote",
            "--single-process",
        ],
        defaultViewport: {
            width: 1366,
            height: 768,
        },
    });
    const page = await browser.newPage();
    await page.goto(process.env.TARGET_URL);
}

Puppetterはv13.5.2を組み込んでいます。

  "dependencies": {
    "puppeteer": "^13.5.2",
    "puppeteer-core": "^10.4.0"
  },

コンテナ化

上記アプリをコンテナ化します。以下の様なDockerfileを用意しました。

FROM public.ecr.aws/lambda/nodejs:14.2022.03.23.16

RUN yum -y install \
    libX11 \
    libXcomposite \
    libXcursor \
    libXdamage \
    libXext \
    libXi \
    libXtst \
    cups-libs \
    libXScrnSaver \
    libXrandr \
    alsa-lib \
    pango \
    atk \
    at-spi2-atk \
    gtk3 \
    google-noto-sans-japanese-fonts \

WORKDIR ${LAMBDA_TASK_ROOT}
COPY app.js package*.json ${LAMBDA_TASK_ROOT}
RUN npm install

CMD [ "app.handler" ]

これをコンテナ化し、ECRにPUSHします。

$ docker build -t sandbox .
$ docker tag sandbox:latest xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/sandbox:latest
$ docker push xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/sandbox:latest

これでLambda関数が正常に起動できることが確認できました。ちないにコンテナ化したときのサイズは624MBでした。