SakuraWi - BLog

WEBエンジニア。聴いたお話をまとめておく倉庫的な。スタックストックスタック!

AWS lambda を使ってRuntime Ruby2.7で実行する方法【ChromeDriver + Selenium + Docker】


経緯

Ruby2.5のサポート終了に伴い、AWS LambdaのランタイムRuby2.5の関数をRuby2.7アップデートする。

技術スタック

  • Ruby2.7
  • ChromeDriver(2.37)
  • Chromium
    • chromium 64.0.3282.167 (stable channel) for amazonlinux:2017.03
  • Selenium(3.142.4)
  • Docker

前提知識として、これらのは動くverを全て一致していないとうまく動作しない。

作業ディレクトリ図

f:id:Saku-Saku:20220103081055p:plain

Dockerfile

最終的にコレで動かしている

FROM public.ecr.aws/lambda/ruby:2.7

# Install dependencies needed to run MySQL & Chrome

RUN yum -y install libX11
RUN yum -y install dejavu-sans-fonts
RUN yum -y install procps
RUN yum -y install mysql-devel
RUN yum -y install tree
RUN mkdir /var/task/lib
RUN cp /usr/lib64/mysql/libmysqlclient.so.18 /var/task/lib
RUN gem install bundler
RUN yum -y install wget
RUN yum -y groupinstall 'Development Tools'

# Ruby Gems

ADD Gemfile ${LAMBDA_TASK_ROOT}/
ADD Gemfile.lock ${LAMBDA_TASK_ROOT}/
RUN bundle config set path 'vendor/bundle' && \
    bundle install

# 日本語フォント
ENV LANGUAGE ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
RUN yum -y install fontconfig
run yum -y install ipa-gothic-fonts && \
    fc-cache -fv \

# Install chromedriver & chromium

RUN mkdir ${LAMBDA_TASK_ROOT}/bin/

# Chromium
RUN wget https://github.com/adieuadieu/serverless-chrome/releases/download/v1.0.0-37/stable-headless-chromium-amazonlinux-2017-03.zip
RUN unzip stable-headless-chromium-amazonlinux-2017-03.zip -d ${LAMBDA_TASK_ROOT}/bin/
RUN rm stable-headless-chromium-amazonlinux-2017-03.zip

# Chromedriver

RUN wget https://chromedriver.storage.googleapis.com/2.37/chromedriver_linux64.zip
RUN unzip chromedriver_linux64.zip -d ${LAMBDA_TASK_ROOT}/bin/
RUN rm chromedriver_linux64.zip

# Copy function code

COPY lambda_function.rb ${LAMBDA_TASK_ROOT}

WORKDIR ${LAMBDA_TASK_ROOT}

RUN tree
RUN ls ${LAMBDA_TASK_ROOT}/bin
# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "lambda_function.lambda_handler" ]

下記のスタックオーバーフローに、動かせたよと言っている人がいるDockerfileを真似たもの。

変更点

  1. 実行ファイル名をlambda_functionに合わせた。
  2. 日本語のフォントのインストール、適用をさせた。これは、seleniumでのfind_elementする時に日本語が必要であったため

ref: https://stackoverflow.com/questions/67841994/which-chromedriver-headless-chrome-versions-exist-that-are-compatible-with-rub

dockerの実行方法

imageのbuild

docker build -t test_name:latest .

imageの実行

docker run -i  -v "$PWD" --shm-size=256m -p 9000:8080 -e ID='YYY' -e PASS='YYY'  delete-item

別ターミナルから、下記curlでdockerのrubyのファイルが実行される( CMD [ "lambda_function.lambda_handler" ] )に一致が必要。

 curl http://localhost:9000/2015-03-31/functions/function/invocations -d '{}'

lambdaのレイヤーへのアップロード (gem)

bundle install --path vendor/bundle

で vendor/bundle 配下にインストール

もしミスったら、一度vendorを削除して入れ直すとよい

vendor/bundle/ruby/2.7.0

となっているのを

ruby/gems/2.7.0 にして、zipにして レイヤーにアップする

lambdaのレイヤーへのアップロード (chromedriver & chromium)

S3にアップしてからレイヤーにアップロード

それぞれの実行ファイルは、Dockerfileに記載しているverを入れる

lambdaの実行設定

  • レイヤーの追加
  • 関数の作成
    • 環境変数の設定
      • pathのためのenviroment production
    • レイヤーの設定
    • イベントの設定
    • メモリ、実行タイムアウト時間の設定

docker内で動いたrubyのコードのスクショの見方

curlなどでコードが実行をする。

save_screenshot('filename.png') などでseleniumはスクショが撮れる。

ので、実行をして、

dockerにbashなどで入って、 ホストのディレクトリにcpコマンドをすれば良い。

docker exec -i -t コンテナid bash
docker cp ec8eca1b6473:/var/task/File02.png .

Lambdaの実行環境

Amanzon Linux 2 での実行となる。

OSは CentOS

fontの設定をする

yum install fontconfig

https://command-not-found.com/fc-cache

以下も参考にした

Seleniumの書き方、コツ

waitさせたい

https://www.selenium.dev/ja/documentation/webdriver/waits/

sleep()

非同期での読みこみを待ちたい時は

sleep(15)

などが有効。

5じゃなくて15で安定して動作したりもした。

docker unable to connect to bin/chromedriver 127.0.0.1:9515

docker unable to connect to bin/chromedriver 127.0.0.1:9515

上記エラーは、chromedriverとchromiumがあっていない時の主なエラー

当初戦っていたエラー

docker run --rm -v "$PWD":/var/task --mount type=tmpfs,target=/dev/shm,readonly=true lambci/lambda:ruby2.7 lambda_function.lambda_handler

上記の実行で、動かない。

chromedriverって起動がいる?

本体のverとruby2.7があってないと動かないのかも。

unable to connect to bin/chromedriver 127.0.0.1:9515

その他参考になるページ