Building Layers
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/building-layers.html
$ sam build layer-logical-id
SAM CLI のバージョンが 0.50.0 以上である必要があります。
$ sam --version
SAM CLI, version 0.50.0
SAM CLI の基本的な使い方については、以前 Qiita にあげたのでこちらも参照いただければと思います。
AWS SAM CLI 再入門 2019.12
https://qiita.com/hayao_k/items/7827c3778a23c514e196
簡単な例
sam init で作成できる Python 3.8 の Hello World Example を例に考えます。
$ sam init --runtime python3.8
$ cd sam-app
$ tree
.
├── events
│ └── event.json
├── hello_world
│ ├── app.py
│ ├── __init__.py
│ └── requirements.txt
├── README.md
├── template.yaml
└── tests
└── unit
├── __init__.py
└── test_handler.py
requirement.txt を確認すると requests モジュールを使用していることがわかります。
(実際は app.py ではコメントアウトされているのですが。。)
requests
これをレイヤー化するする場合、template.yaml の Resources を以下のように書き換えます。
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.8
Layers:
- !Ref MyLayer
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
MyLayer:
Type: AWS::Serverless::LayerVersion
Properties:
Description: Layer description
ContentUri: 'my_layer/'
CompatibleRuntimes:
- python3.8
Metadata:
BuildMethod: python3.8
SAM CLI で Lambda Layers をビルドするには レイヤーリソース (例では MyLayer)の
メタデータ属性として BuildMethod を記述する必要があります。
Metdata:
BuildMethod: python3.8
ContentUri に 記載したディレクトリを作成し、requirements.txt を移動します。
mkdir ./my_layer
mv ./hello_world/requirements.txt ./my_layer/
sam build MyLayer でレイヤーをビルドできます。
$ sam build MyLayer
Building layer 'MyLayer'
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Build Succeeded
Built Artifacts : .aws-sam/build
Built Template : .aws-sam/build/template.yaml
Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided
前述のとおり template.yaml に BuildMethod を指定していないとエラーになります。
$ sam build MyLayer
Layer <samcli.lib.providers.sam_function_provider.SamFunctionProvider object at 0x7f3147f93f90> is missing BuildMethod Metadata.
Error: Build method missing in layer MyLayer.
.aws-sam/build/MyLayer 配下に requests モジュールがダウンロードされていることがわかります。
$ tree -a -L 5
.
├── .aws-sam
│ └── build
│ ├── MyLayer
│ │ └── python
│ │ ├── certifi
│ │ ├── certifi-2020.4.5.1.dist-info
│ │ ├── chardet
│ │ ├── chardet-3.0.4.dist-info
│ │ ├── idna
│ │ ├── idna-2.9.dist-info
│ │ ├── requests
│ │ ├── requests-2.23.0.dist-info
│ │ ├── requirements.txt
│ │ ├── urllib3
│ │ └── urllib3-1.25.9.dist-info
│ └── template.yaml
├── events
│ └── event.json
├── .gitignore
├── hello_world
│ ├── app.py
│ └── __init__.py
├── my_layer
│ └── requirements.txt
├── README.md
├── template.yaml
└── tests
└── unit
├── __init__.py
└── test_handler.py
単に sam build とした場合はアプリケーション全体がビルドされますが、
今回の例の場合、hello_world/ 配下の requirements.txt が存在しないためエラーとなります。
$ sam build
Building function 'HelloWorldFunction'
Running PythonPipBuilder:ResolveDependencies
Build Failed
Error: PythonPipBuilder:ResolveDependencies - Requirements file not found: /tmp/sam-app/hello_world/requirements.txt
アプリケーションのディレクトリ配下の requirements.txt にはデプロイパッケージに
含めるモジュールを記載し、Layer ディレクトリの requirements.txt には Lambda Layers に
含めるモジュールを記載していれば、sam build コマンドで全体をビルドできます。
あとはいつもどおり sam deploy すれば OK です。
$ sam deploy
or
$ sam deploy --guided
非常にシンプルかつ、簡単に実行できました。
ただ複数のランタイムバージョンやネイティブバイナリを扱う場合などは
これだけだと物足りない場合もあるかもしれません。
このあたりは 以前 docker-lambda を使用して Lambda Layers を作成する記事を書いたので
興味のある方は参照いただければと思います。
Lambda Layersを作成する時はdocker-lambdaやyumdaが便利
https://qiita.com/hayao_k/items/a6fd8ecfb1f937246314
簡単ですが、以上です。
参考になれば幸いです。