LoginSignup
1
1

More than 1 year has passed since last update.

Layer付きのAWS Lambda functionをServerlessFrameworkでローカル実行するとLayerが参照できない

Posted at

概要

タイトルの通り、Layerを用いて一部ライブラリを共通化しているAWS Lambda functionを、serverlessでローカル実行しようとした時につまずいたので備忘録として残しておく。

経緯

最近、趣味でAWS Lambda上で動かすpythonプログラムを作成していて、デプロイが楽になるとのことなのでserverlessを導入していた。
その際、functionを複数作成しており、一部ライブラリはLayerを用いて共通化していた。

作成したプログラムの構成は以下。

プロジェクトルートディレクトリ
├─function1
│  └─src
│     └─handler.py
├─function2
│  └─src
│     └─handler.py
├─layer
│  ├─layer1
│  │  └─layer1のpythonライブラリ・ソース群
│  └─layer2
│     └─layer2のpythonライブラリ・ソース群
└─serverless.yml

また、serverless.ymlの記述内容は以下。
(本記事に関係ない細かな設定については省略している)

serverless.yml

layers:
  layer1:
    path: layer/layer1
    name: ${self:service}-layer1
    compatibleRuntimes:
      - python3.7
    allowedAccounts:
      - "*"
  layer2:
    path: layer/layer2
    name: ${self:service}-layer2
    compatibleRuntimes:
      - python3.7
    allowedAccounts:
      - "*"
functions:
  function1:
    handler: function1/src/handler.lambda_handler
    layers:
      - { Ref: Layer1LambdaLayer }
      - { Ref: Layer2LambdaLayer }
  function2:
    handler: function2/src/handler.lambda_handler
    layers:
      - { Ref: Layer1LambdaLayer }
      - { Ref: Layer2LambdaLayer }

この設定でsls deployコマンドを実行すると、AWSへのデプロイは正常終了し、Lambda上でのpythonプログラムの起動もできるのだが、
何故かsls invoke local --function {function名}コマンドによるローカル実行は下記エラーが発生してうまくいっていなかった。

ModuleNotFoundError: No module named '{layerに配置したライブラリ名}'

どうやら、ローカル実行するとlayerに配置したライブラリが参照できていないらしい。
AWSにデプロイするとちゃんと動くのに。解せぬ。

解決策

とにかくserverlessでローカル実行するとlayerをうまく参照できていないことがわかったので、コマンド実行時にオプションなどで設定を追加できないか公式ドキュメントを調べてみた。

…うーん、それっぽいオプションは見当たらない。
というかデータ入力の方法についての記述が大半でLayerについての説明なんかは皆無なんだなこれが。

とりあえずオプションを一通り試してみるかー、と半ばやけくそになりかけた時、気になる記述を見つけた。

--docker Enable docker support for NodeJS/Python/Ruby/Java. Enabled by default for other runtimes.

訳)--dockerオプションは、NodeJS / Python / Ruby / JavaのDockerサポートを有効にします。他のランタイムではデフォルトで有効になっています。

へー。pythonだとDockerはデフォルトで無効化されてるんだー。へー。
…ひょっとしてこれじゃね?

serverlessではなくAWS CLIを使ってLambda functionをローカルで実行するときは、ローカルのDocker上にLambdaの実行環境が作成されそこでfunctionが実行されることは知っていたのでそこから連想できた。

とにもかくにも、--dockerオプションを追加してコマンドをたたいてみる。

>sls invoke local --function function1 --docker
Serverless: Running "serverless" installed locally (in service node_modules)

(略)

{"statusCode":200,"body":"{\"message\": \"finished . !\"}"}

動いた!!!

どうやらlayerが参照できなかったのは、docker上で動かしてなかったからだった模様。
作成したfunctionを正しく動かすためにはほぼ本番に近いdocker上の環境で動かす必要があるのに、その設定はデフォルトで無効になっているという…。
いやまあ毎回docker上で動かしていると実行が遅くなったりするし、Lambda functionはLayer使わないものが大半だったりするとデフォルト無効の意義も理解はできるんだが…。
ちょいと公式ドキュメントが分かりづらすぎやしませんかね?

結論

Layerでライブラリを共通化したLambda functionがserverlessでローカル実行できない、といった事象に遭遇した方はコマンドに--dockerオプションを付け加えてみてはいかがだろうか。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1