カピバラ好きなエンジニアブログ

ITのこととか趣味のカメラのことなどを赴くままに書いていきます。カピバラの可愛さこそ至高。

Lambda Layerに外部のライブラリをアップロードする

Lambdaで外部のライブラリを使用する場合、Lambda Layerにアップロードして使用するやり方があります。

今回はそのやり方を試していきます。
尚、環境はPython3.7で実施しています。

以下の記事を参考にさせていただきました。
lets-hack.tech

実施作業

はじめに

今回Layerを実行するFunctionのコードは以下になります。

import json
from dataclasses import dataclass
from dataclasses_json import dataclass_json

@dataclass_json
@dataclass
class TestColumns:
    column1: str = None
    column2: str = None
    column3: str = None
    
def exec_function(event):
    column_list = TestColumns()
    column_list.column1 = "hoge"
    column_list.column2 = "huga"
    column_list.column3 = "hogehuga"

    print(column_list)

    column_list_json = column_list.to_json(indent=4)

    print(column_list_json)

def lambda_handler(event, context):
    exec_function(event)



処理的には定義したdataclassにデータを入れて、jsonに変換して表示するだけの簡単なコードになりますが、dataclasses_json は外部のライブラリなのでLambdaだと以下のようなエラーが出てしまいます。

Response:
{
  "errorMessage": "Unable to import module 'lambda_function': No module named 'dataclasses_json'",
  "errorType": "Runtime.ImportModuleError"
}

Request ID:
"b73c19a9-1511-4219-9dee-9702d2ee8599"

Function Logs:
START RequestId: b73c19a9-1511-4219-9dee-9702d2ee8599 Version: $LATEST
[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'dataclasses_json'
END RequestId: b73c19a9-1511-4219-9dee-9702d2ee8599
REPORT RequestId: b73c19a9-1511-4219-9dee-9702d2ee8599	Duration: 1.90 ms	Billed Duration: 100 ms	Memory Size: 128 MB	Max Memory Used: 50 MB	Init Duration: 123.04 ms	



そのため今回はdataclasses_json のライブラリをLambda Layerにアップロードしていきます。

アップロードファイル作成

作業はコマンドプロンプトで行っていきます。
python、pipはインストールされている前提で進めていきます。


最初に作業ディレクトリ配下で以下のコマンドを実行します。

# mkdir python
# cd python



ディレクトリの移動までできたら以下のコマンドで外部ライブラリをカレントディレクトリ配下にインストールします。

# python -m pip install dataclasses_json -t .



コマンドが正常終了したら、カレントディレクトリ配下に以下のファイル・フォルダが存在していることを確認します。

bin
dataclasses_json
dataclasses_json-0.5.1.dist-info
marshmallow
marshmallow-3.6.1.dist-info
marshmallow_enum
marshmallow_enum-1.5.1.dist-info
mypy_extensions-0.4.3.dist-info
mypy_extensions.py
stringcase-1.2.0.dist-info
stringcase.py
typing_extensions-3.7.4.2.dist-info
typing_extensions.py
typing_inspect-0.6.0.dist-info
typing_inspect.py
__pycache__



以下のコマンドを実行し、インストールした外部ライブラリを1つのファイルに圧縮します。
コマンドプロンプトはzipコマンドがないので、powershellのコマンドで実行しています。

# cd ../
# powershell -Command "Compress-Archive -Path python -DestinationPath python.zip -Force"


無事にzipファイルが作成されていれば、zipファイルの作成は完了です。

Lambda Layerアップロード

ここからはAWSのマネジメントコンソールから操作を行います。
ログインして、Lambdaコンソールを開き、以下の手順でLambda Layerの作成を行っていきます。
f:id:live-your-life-dd18:20200618153104p:plain


アップロードする際の名前は他のレイヤーと区別がつくのであれば何でも良いです。
ランタイムはアップロードするライブラリの互換性に合わせて設定して下さい。
真ん中のアップロードから先ほどのzipファイルを指定して実行します。
f:id:live-your-life-dd18:20200618153350p:plain

f:id:live-your-life-dd18:20200618153534p:plain


エラーなくレイヤーが作成されればアップロードは完了です。
f:id:live-your-life-dd18:20200618155138p:plain

Lambda Functionに設定・実行

レイヤーがアップロードできたら、実際に使用できるか試していきます。
設定するFunctionからレイヤーの追加を行います。
f:id:live-your-life-dd18:20200618154007p:plain


先ほど作成したレイヤー名とバージョンを指定して追加ボタンを押下します。
f:id:live-your-life-dd18:20200618154133p:plain


Layersの表示が(1)となっていれば完了です。
f:id:live-your-life-dd18:20200618154215p:plain


Functionを実行し、出力内容からdataclassに設定したデータがjson形式で表示されていることが確認出来ました。

Request ID:
"5becf16b-b0a1-46e9-be09-0da1ea47ecd3"

Function Logs:
START RequestId: 5becf16b-b0a1-46e9-be09-0da1ea47ecd3 Version: $LATEST
TestColumns(column1='hoge', column2='huga', column3='hogehuga')
{
    "column1": "hoge",
    "column2": "huga",
    "column3": "hogehuga"
}
END RequestId: 5becf16b-b0a1-46e9-be09-0da1ea47ecd3
REPORT RequestId: 5becf16b-b0a1-46e9-be09-0da1ea47ecd3	Duration: 1.92 ms	Billed Duration: 100 ms	Memory Size: 128 MB	Max Memory Used: 54 MB	Init Duration: 194.95 ms	


感想及び所感

ということで、問題なく外部ライブラリをLambda Layerとしてアップロードすることができました。

本当はSAM使うと「zipファイルを作成して...」という手間がないのですが、今回は敢えて手間のかかるやり方でやってみました。