たまにPlaywrightをLambdaで動かしたくなりますよね。
すでにいろいろな方が挑戦されているようで、簡単に使えるLambdaレイヤーが公開されているようです。
ただ、そういうことじゃないんです。自分でやることに意味があるんです。なんとか動作しましたので、ご紹介。
きっかけ
先日投稿したこちらの記事で、LangChainの「AsyncChromiumLoader」を紹介しました。
これをLambda化したいなぁと思ったのがきっかけです。(そしてBedrock Agentsから呼び出したい)
AsyncChromiumLoaderは内部でPlaywrightが使われているのですが、先ほど解説した「chromium.launch
」の呼び出し部分のargsを外部から指定する方法がなかったので、素のPlaywrightを使って検証しました。
Lambda化ができたので、あとはBedrock Agentsのアクショングループとして登録してやれば、Web検索ができるエージェントが作成できる!
はずでした。。。
Bedrock Agentsのクオータ制限で、「Lambda レスポンスペイロードサイズは25KBまで」というものがあり、この制限に引っかかってしまうサイトが多く、実用には至りませんでした。
Playwrightを動作させる条件を確認
システム要件
- Python 3.8 or higher.
- Windows 10+, Windows Server 2016+ or Windows Subsystem for Linux (WSL).
macOS 13 Ventura, or macOS 14 Sonoma. - Debian 11, Debian 12, Ubuntu 20.04 or Ubuntu 22.04, Ubuntu 24.04, on x86-64 and arm64 architecture.
インストール手順
Playwrightのインストールはpip install playwright
だけではなく、ブラウザのダウンロードなどの手順が必要です。
pip install playwright
playwright install --with-deps chromium
--with-deps
はシステムの依存ライブラリをあわせて行うオプションです
Lambdaで同様のことを行う必要があるため、zip形式ではなくコンテナイメージ形式で作成します。
Dockerfileを作成
AWSが提供するベースイメージ(public.ecr.aws/lambda/python:3.12)はOSがAmazon Linux 2023のため、Playwrightのシステム要件に合致しません。そのため、インストール手順を実行してもエラーになってしまいます。
BEWARE: your OS is not officially supported by Playwright; installing dependencies for ubuntu20.04-x64 as a fallback.
Installing dependencies...
sh: line 1: apt-get: command not found
Failed to install browsers
Error: Installation process exited with code: 127
「ランタイムインターフェイスクライアントで代替ベースイメージを使用する」を参考に、AWS提供ではないベースイメージを使用する方法を採用します。
参考サイトを少しカスタマイズし、以下のようなDockerファイルを作成します。
ベースイメージはpython:3.12-slimです。
# Define custom function directory
ARG FUNCTION_DIR="/function"
# Use a slim version of the base Python image to reduce the final image size
FROM python:3.12-slim
# Include global arg in this stage of the build
ARG FUNCTION_DIR
ENV PLAYWRIGHT_BROWSERS_PATH=/playwright
# Copy function code
RUN mkdir -p ${FUNCTION_DIR}
COPY requirements.txt ${FUNCTION_DIR}
# Set working directory to function root directory
WORKDIR ${FUNCTION_DIR}
# Install the function's dependencies
RUN pip install -r requirements.txt && \
playwright install --with-deps chromium
COPY app.py ${FUNCTION_DIR}
# Set runtime interface client as default command for the container runtime
ENTRYPOINT [ "/usr/local/bin/python", "-m", "awslambdaric" ]
# Pass the name of the function handler as an argument to the runtime
CMD [ "app.lambda_handler" ]
「PLAYWRIGHT_BROWSERS_PATH」を指定しない場合、chromiumが「/root/.cache/ms-playwright」配下にダウンロードされます。Lambdaの実行ユーザーはrootではないため、「PLAYWRIGHT_BROWSERS_PATH」を明示的に指定します。
PLAYWRIGHT_BROWSERS_PATHは、Lambdaの環境変数にもセットする必要があります。
Resources:
PlaywrightFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
PackageType: Image
Architectures:
- x86_64
Environment:
Variables:
PLAYWRIGHT_BROWSERS_PATH: /playwright # これ!
Metadata:
Dockerfile: Dockerfile
DockerContext: ./hello_world
DockerTag: python3.12-v1
その他のコードを作成
requirements.txtを作成します。
awslambdaric
playwright
awslambdaricは、「AWS Lambda Python Runtime Interface Client」です。これをインストールすると、AWS提供ではないベースイメージでも簡単にLambdaで動作させることができます。
最後にPythonコードを作成します。
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(
args=[
"--single-process",
"--no-zygote",
"--no-sandbox",
"--disable-gpu",
"--disable-dev-shm-usage",
"--headless=new",
]
)
context = browser.new_context(user_agent=user_agent)
page = context.new_page()
response = page.goto(url=url)
content = page.content()
title = page.title()
browser.close()
argsオプションを指定します。
オプション | 説明 |
---|---|
--single-process | Runs the renderer and plugins in the same process as the browser |
--no-zygote | Disables the use of a zygote process for forking child processes. Instead, child processes will be forked and exec'd directly. Note that --no-sandbox should also be used together with this flag because the sandbox needs the zygote to work. |
--no-sandbox | Disables the sandbox for all process types that are normally sandboxed. Meant to be used as a browser-level switch for testing purposes only. |
--disable-gpu | Disables GPU hardware acceleration. If software renderer is not in place, then the GPU process won't launch. |
--disable-dev-shm-usage | The /dev/shm partition is too small in certain VM environments, causing Chrome to fail or crash (see http://crbug.com/715363). Use this flag to work-around this issue (a temporary directory will always be used to create anonymous shared memory files). |
--headless=new | Run in headless mode, i.e., without a UI or display server dependencies. |
それぞれの意味はよくわかりませんが、以下を参考に設定したところうまく動作しました。
引用元:https://peter.sh/experiments/chromium-command-line-switches/
これでうまくいくと思います。