requirements.txt を Lambdaレイヤーに分離してみた

requirements.txt を Lambdaレイヤーに分離してみた

SAMで requirements.txt を Lambdaレイヤーに分離してみました
Clock Icon2025.02.03

はじめに

こんにちは、アノテーションのなかたです。
今回は、SAMでrequirements.txtを Lambdaレイヤーに分離してみました。

Lambdaレイヤーとは

Lambda レイヤーは、補足コードまたはデータを含む .zip ファイル アーカイブです。レイヤーには通常、ライブラリ依存関係、カスタム ランタイム、または構成ファイルが含まれます。

アプリケーションコードのうち、ライブラリやパッケージなどの依存関係を別の層として切り出してレイヤーとして利用するようです。

これにより、アプリケーションコードに関心が集まったり、独立して依存関係のみを更新することができます。
また、レイヤーとして切り出すことにより、別の関数で使い回すこともできます。

やってみる

1. SAMプロジェクトの構築

とりあえずSAMプロジェクトを構築し、SAMプロジェクトがデプロイすることを確認します。

sam init # Python3.13、`hello-world`テンプレート
cd プロジェクトフォルダ

sam build
sam deploy

マネジメントコンソールにてデプロイされているか確認します。
関数の作成ができており、この時点ではLambdaレイヤーは0と表示されています。
スクリーンショット 2025-02-03 17.44.01

また、Pythonのプロジェクトを作成すると、requirements.txt で requestsライブラリが依存先としてデフォルで定義されています。
そのため requests ライブラリに関連したフォルダが展開されています。
スクリーンショット 2025-02-03 17.44.49

2. Lambdaレイヤー用のフォルダを作成する

SAMのLambdaレイヤーリソースにあたるAWS::Serverless::LayerVersionでは、ContentUrlプロパティ属性があります。
この属性でフォルダを参照し、そのフォルダ下のソースコードやパッケージをLambdaレイヤーとして登録します。
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-resource-layerversion.html#sam-layerversion-contenturi

今回は、requirements.txt を別のフォルダに移動し、ライブラリを独立させてみます

% tree
.
├── README.md
├── __init__.py
├── hello_world
│   ├── __init__.py
│   └── app.py
├── my_layer  # Lambdaレイヤーで参照するフォルダ
│   └── requirements.txt  # requestsライブラリが定義されている
├── samconfig.toml
├── template.yaml

3. Lambdaレイヤーを定義する

SAMテンプレートに Lambdaレイヤーのサンプルを定義してみます。
コードは公式ドキュメントからお借りしましたが、Pythonのバージョンのみ異なっていたため、3.13 に合わせています。

template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  demo-lambda-layer

  Sample SAM Template for demo-lambda-layer

Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.13
+      Layers:
+        - !Ref MyLayer
      Architectures:
        - x86_64
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello
            Method: get

+  MyLayer:
+    Type: AWS::Serverless::LayerVersion
+    Properties:
+      ContentUri: my_layer/
+      CompatibleRuntimes:
+        - python3.13
+    Metadata:
+      BuildMethod: python3.13

Outputs:
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

念のため構文があっているかバリデーションしつつ、ビルド、デプロイします。

sam validate
sam build
sam deploy

4. デプロイの確認

マネジメントコンソールから Lambda関数を確認します。
Lambda関数にレイヤーが 1つ登録されていることがわかります。
スクリーンショット 2025-02-03 17.59.19
スクリーンショット 2025-02-03 17.59.50
ソースコードフォルダからもライブラリのフォルダが消えていることがわかります。
スクリーンショット 2025-02-03 17.59.36

5. Lambdaレイヤーにあるライブラリを用いて、プログラムを実行してみる

本当にレイヤーに格納されているライブラリを用いることができるのか確認してみます。
サンプルプログラムにあったrequestsライブラリでIPアドレスを確認するプログラムを実行します。

hello_world/app.py
import json

import requests

def lambda_handler(event, context):
    try:
        ip = requests.get("http://checkip.amazonaws.com/")
    except requests.RequestException as e:
        raise e

    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": "hello world",
            "location": ip.text.replace("\n", "")
        }),
    }

テストを実行したところ、ライブラリが正常に動作していることが確認できました。

Status: Succeeded
Test Event Name: (unsaved) test event

Response:
{
  "statusCode": 200,
  "body": "{\"message\": \"hello world\", \"location\": \"<IPアドレス>\"}"
}

Function Logs:
START RequestId: dummy-request-id Version: $LATEST
END RequestId: dummy-request-id
REPORT RequestId: dummy-request-id	Duration: 147.63 ms	Billed Duration: 148 ms	Memory Size: 128 MB	Max Memory Used: 58 MB

Request ID: dummy-request-id

おわりに

ライブラリが多く存在するSAMプロジェクトにおいて、自作したフォルダとライブラリのフォルダが混在してわからないという問題に直面したことがありました。
今回のようにLambdaレイヤーを用いることで解決できそうです。

参考

https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/building-layers.html

アノテーション株式会社について

アノテーション株式会社はクラスメソッドグループのオペレーション専門特化企業です。サポート・運用・開発保守・情シス・バックオフィスの専門チームが、最新 IT テクノロジー、高い技術力、蓄積されたノウハウをフル活用し、お客様の課題解決を行っています。当社は様々な職種でメンバーを募集しています。「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、アノテーション株式会社 採用サイトをぜひご覧ください。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.