LambdaとLayersは便利ですが、1つの関数につき上限は5つまでと制限があります。
Layersは=1モジュールとして運用しているケースが多いかと思いますが、意外と足りなくなったり1つずつ追加するのは手間です。
お気に入りのモジュールたちはお馴染みのrequirement.txt
で管理し、1つのレイヤーにまとめてしまいましょう。
テストで6つのモジュールをインポートするrequirement.txtを作成します。
selenium
requests
Pillow
lxml
numpy
Flask
そして同階層にて以下のスクリプトを実行します。dockerの
pythonのバージョンや、awsコマンドの引数は必要に応じて編集してください。
mkdir -p python/bin/
docker run --rm -v $(pwd):/var/task -w /var/task lambci/lambda:build-python3.7 pip install -r requirements.txt -t ./python
zip -r layer.zip python
aws lambda publish-layer-version --layer-name favorites --zip-file fileb://layer.zip --compatible-runtimes python3.7 --region ap-northeast-1
rm -rf layer.zip python
Lambdaに登録されたレイヤーを追加できるようになりました。テスト関数はこのレポジトリからServerless Frameworkによるデプロイ・確認を行いました。以上です!
Serverless Frameworkを使うならserverless-python-requirementsを使えばモジュール管理は楽になりますし、レイヤーを使って分離しない方がInfrastructure as Codeの徹底がされていてエレガントだと思います。しかしレイヤー数の上限が障害になったり、モジュールがパッケージに含まれるとデプロイの待ち時間が長くなるので、個人的にはレイヤーで分離するほうが小回りが聞いて好みです。
ちなみにseleniumを使うならバイナリも一緒にあげて管理すると楽です。以下がバイナリも追加するスクリプトです。
余談ですが、私が把握しているlambdaでpythonで動くheadlessなseleniumはこのスクリプトのバージョンとpython3.7のセットです。古いリリースのバージョンを使っているのはそのためです。
mkdir -p python/bin/
+ 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 headless-chromium.zip -d python/bin/
+ curl -SL https://chromedriver.storage.googleapis.com/2.37/chromedriver_linux64.zip > chromedriver.zip
+ unzip chromedriver.zip -d python/bin/
+ rm -rf chromedriver.zip headless-chromium.zip
docker run --rm -v $(pwd):/var/task -w /var/task lambci/lambda:build-python3.7 pip install selenium -t ./python
zip -r layer.zip python
aws lambda publish-layer-version --layer-name selenium_with_bin --zip-file fileb://layer.zip --compatible-runtimes python3.7 --region ap-northeast-1
rm -rf layer.zip python
seleniumがlambda上で正しく動くためのchromeOptionsやこのレイヤーから得るバイナリのパスを設定したテスト関数はこちらです。
参考
https://github.com/adieuadieu/serverless-chrome/issues/133
https://dev.classmethod.jp/articles/managing-external-modules-with-serverless-framework-plugin/
https://www.npmjs.com/package/serverless-python-requirements
https://hacknote.jp/archives/49974/
https://dev.classmethod.jp/articles/lambda-layer-first-action/