⛳
ECSでSeleniumを実行する際の注意点
通常、SeleniumをAWS上で実行する際はLambdaがよく利用される。しかし15分を超過するとLambdaが使用できなくなり、ECS on Fargateが代替手段となるので簡単に解説したい。
SeleniumをLambdaで実行する場合
まずSeleniumをLambdaで実行する際の参考となるサイトは以下があり、方法は次の通り。
- Pythonのパッケージと、Seleniumで必要となるchromedriver、headless-chromiumをCloud9上でインストールしてローカルにZipでダウンロード。
- ZipファイルをLambda関数のレイヤーに設置し、Python3.7でSeleniumを実行する。
しかし、この方法だと次の2点で問題がある。
- Lambdaのスペックを超過する重い処理ができない(15分超過やメモリ/ストレージの容量超過)。
- Lambdaレイヤーに設定できるZipファイルの容量に限界があり、必要なパッケージをインストールできない場合がある。
よって上記の問題からLambdaが使えない場合、同じサーバレスで実行する場合はECS on Fargateの手段を検討する必要がある。
SeleniumをECSで実行するためのDockerHub
次にECSでSeleniumを実行するにあたり、最も手軽な方法はDockerHubにある以下のベースイメージを利用することである。他の参考サイトもこちらを利用している。
当初、このイメージを利用する方法でトライしたが、M1 MacでDocker BuildするとエラーでBuildできない問題に直面したため、上記のSelenium Lambdaの方法をDockerで実行する方法を検討した。SeleniumをDockerで実行するためのDockerFile
結論として、DockerFileを以下のように記述してBuildした。
DockerFile
FROM python:3.7 as build
# chromedriver & headless-choronium for selenium
RUN apt-get install -y unzip && \
curl -SL https://chromedriver.storage.googleapis.com/2.37/chromedriver_linux64.zip > chromedriver.zip && \
curl -SL https://github.com/adieuadieu/serverless-chrome/releases/download/v1.0.0-37/stable-headless-chromium-amazonlinux-2017-03.zip > headless-chromium.zip && \
unzip chromedriver.zip -d /opt/ && \
unzip headless-chromium.zip -d /opt/
FROM python:3.7
COPY --from=build /opt/headless-chromium /opt/
COPY --from=build /opt/chromedriver /opt/
# set display port to avoid crash
ENV DISPLAY=:99
ENV AWS_REGION=ap-northeast-1
WORKDIR /tmp
COPY requirements.txt /tmp/
RUN \
apt update && \
apt upgrade -y && \
pip install --upgrade pip && \
pip install --no-cache-dir -r requirements.txt
# chromedriver動作時のエラー(Status code was: 127)回避
RUN apt-get install -y libglib2.0-0 libgconf-2-4 libfontconfig1 libnss3
COPY main.py /tmp/
CMD python3.7 main.py
注意点は以下の通りである。
- pythonのバージョンは3.7としている。これはダウンロードするchromedriver、headless-chromiumが3.7でないと起動しないためである。
-
RUN apt-get install -y libglib2.0-0 libgconf-2-4 libfontconfig1 libnss3
の記述が必要。これはchromedriver動作時のエラー(Status code was: 127)を回避するためである。 - requirement.txtに追加でインストールしたいPythonパッケージを記述する。
requirement.txt
boto3
pandas
selenium==4.1.0
- Docker Buildする際はdocker build --platform linux/amd64 -t <ECR> .とX86_64でbuildする必要がある。ARM64で起動するとエラーになる。
Seleniumのコード
上記のDockerFileとセットとなるmain.pyのサンプルコードである。
main.py
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
def selenium_execute():
options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("--disable-gpu")
options.add_argument("--hide-scrollbars")
options.add_argument("--single-process")
options.add_argument("--ignore-certificate-errors")
options.add_argument("--window-size=880x996")
options.add_argument("--no-sandbox")
options.add_argument("--homedir=/tmp")
options.add_experimental_option("w3c", True)
options.binary_location = "/opt/headless-chromium"
prefs = {"browser.downloads.dir": "//tmp//", "download.default_directory": "//tmp//", "directory_upgrade": True}
options.add_experimental_option("prefs", prefs)
options.add_experimental_option('excludeSwitches', ['enable-logging'])
#ブラウザの定義
driver = webdriver.Chrome(
"/opt/chromedriver",
options=options
)
# ダウンロード実行可能に変更
driver.command_executor._commands["send_command"] = ("POST", '/session/$sessionId/chromium/send_command')
params = {
"cmd": "Page.setDownloadBehavior",
"params": {"behavior": "allow", "downloadPath": '//tmp//'},
}
driver.execute("send_command", params)
driver.get("http://XXXXX")#サイトにアクセス
if __name__ == '__main__':
selenium_execute()
注意点は以下の通りである。
- chromedriver、headless-chromiumの配下をDockerFileで設置する場所に合わせる
- Seleniumでダウンロードする際は、ECSにあるディレクトリをする。今回は以下のように/tmp/にダウンロードするよう指定している。
prefs = {"browser.downloads.dir": "//tmp//", "download.default_directory": "//tmp//", "directory_upgrade": True}
以上の注意点に気をつければエラーを回避してECSでSeleniumを実行できる。
ECS on Fargateの実行方法については、以下のサイトを参考にされたい。
Discussion