【2024年春Ver.】AWS Lambda Layerの作成方法をわかりやすく解説【Python3.12】

1年ぶりにAWS Lambdaでやってみたいことができて、新しいライブラリを入れるためにLayerを作ろうと[自分の過去記事](https://qiita.com/__DASHi__/items/268062f0dba0e93170f2)見ながらAWS Cloud9を久しぶりに開いてみたら、ちょいちょい変わっているところがあって「まあAWSだもんね、そうだよね」と勝手に納得していました。

この記事は、そんなAWS Lambdaを久しぶりに触った私が将来読んでも引っかからずに作業できるよう、AWS Lambda Layerを簡単に作成する方法を解説する備忘録です。

## 1. Lambda Layerとは

まずは、Lambda Layer（”Lambda”はラムダ、”Layer”はレイヤーと読みます）とは何？という話から。

**AWS公式サイトより**

> Lambda レイヤーは、補助的なコードやデータを含む .zip ファイルアーカイブです。レイヤーには通常、ライブラリの依存関係、カスタムランタイム、または設定ファイルが含まれています。（出典：[https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-layers.html](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-layers.html) ）
> 

かなり乱暴にこの説明を翻訳すると「**pip installで追加したモジュールをlambdaでも使いたい時の方法」** となります。

上級者の方からはめちゃくちゃ怒られそうな説明ですが、最初の一歩としてはこの理解で十分です。「本来の」使い方は、Lamdba関数を作りなれていけば追々分かっていくでしょう。

### 1-1. Lambda Layerが必要になる時

Pythonで参考文献を見ながらプログラムを作っていると、`No module named ‘xxxxxx’`的なエラーに遭遇することがあります。スペルエラーとかの場合は除けば、サードパーティ製のライブラリを使っている場合にこのエラーが起きることが多いですね。そして、ググったりして`pip install ‘xxxxxx’`とすることで解決することが多いと思います。

例えば、これは最近Claude3を使ってみたくて私が作ったLambda関数ですが、ずらっと並ぶimport文の中で、上段の`time`とか`json`とかはPythonの標準ライブラリなので、特になにもせずにAWS Lambdaでもそのまま使えますが、下段にあるopenaiは（一般の開発環境では`pip install`する）サードパーティー製のライブラリで、そのままではLambda関数を動かすことはできません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/3d9e101f-dd7a-8ae4-087c-5cd69a9ad642.png)

こういった場合に、や`openai`をLambda Layerとしてアタッチ（≒インストール）することで、Lambda関数でもサードパーティー製のライブラリを動かすことができる、という訳です。

ちなみに、今回はlambdaからClaude3を使うためには最新版の`boto3`ライブラリが必要だったためLayerを作成している、という感じです。

実際に、上のコードが書かれているLambda関数の概要を見ると、Layersの欄に`(2)`という数字が出ています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/326c3149-1522-10a9-e0ec-8ada3382a473.png)

そしてLayers欄をクリックすると、以下のようにこの関数にアタッチされているライブラリの一覧が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/09f88d22-d77d-ddc5-7b1d-e6e2364ceba7.png)

と、こんな感じでLayerを使うことでAWS Lambda上でもサードパーティー製のライブラリを使うことができるようになります。

### 1-2. Lambda Layerの制限

さて、さっそくLambda Layerを作ってみよう、と行きたいところですが、その前に知っておかないといけないLambda Layerの制限があります。これを知らなかった1年前の私は散々ハマり倒しました。ですから気ははやっても以下の制限事項は一読しておくことをお勧めします。

**レイヤー数は５つまで**

1つのLambda関数にアタッチできるレイヤーは最大で5個までです。5個を超えるレイヤーを登録しようとすると以下のようなエラー表示が出てしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/ae87cb9b-f37c-1296-6a51-3c1da4b41cb3.png)

Lambda関数は単機能なことが多いので通常この制限が問題になることは少ないですが、あれもこれもとライブラリをimportしているプログラムでは、5つ以上のレイヤーが必要になることもあるかもしれません。その場合は以下のように対応します。

- **２つ以上のライブラリを合体させたLayerを作成する**：後述する容量制限を超えなければ、１つのLayerに複数のライブラリを搭載することは問題ありません。複数のライブラリをLayerに組み込む方法については記事の後半で取り上げます。
- **必要のないライブラリをimportしない**：まずは「importはしているけど使っていない」ライブラリがないかチェックしましょう。さらに減らす必要がある場合は、API呼び出しのラッパとして使われているライブラリ（私の上のLamdba関数で言えばOpenAIとかLINE Messaging APIとかがそれに当たります）について、ライブラリを使わずAPIを直接呼び出す形に変えたり、似たような機能のライブラリを複数インストールしているのであればどちらか一つにまとめたり、というような作業が必要になるでしょう。

ただし、そもそもサードパーティライブラリをたくさんimportしているLambda関数は起動（コールドスタート）に時間がかかります。せっかくのLambda関数の軽量・軽快というメリットが薄れてしまうので、できる限りLambda関数はシンプルに、サードパーティライブラリも少なく設計するのがオススメです。

**圧縮後のサイズは50MBまで**

Layerはzipファイルでアップロードしますが、このzipファイルのサイズには2つの制限があります。

- 圧縮されたzipファイルのサイズが50MBを超えないこと
- 展開後のファイルサイズが250MBを超えないこと

例えば、50MBより大きいzipファイルをアップロードしようとするとこのようなエラーが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/6e6d5f29-eedc-3ee0-5405-4d4fbc7f3531.png)

PandasやMecab等一部の巨大ライブラリをLayerにしようとすると、この制限に当たることがあります。この場合は以下のような解決法があります

- **自分でライブラリの中を整理して不要なファイルを削除する**：pip install -tなどで特定のディレクトリにインストールして、その中をのぞくと分かりますが、依存関係のために大量の参照ライブラリが一緒にインストールされていることがあります。この中には、他のLayerに既に含まれているものもあるかもしれません。そういった重複したライブラリをコツコツ削除していくと、容量を削減することができます。ただ、これはなかなかに大変な作業です。
- ライブラリの軽量版を探してくる：もし見つけることができるならこれが一番手っ取り早いです。例えばPandasなら[https://aws-sdk-pandas.readthedocs.io/en/stable/layers.html](https://aws-sdk-pandas.readthedocs.io/en/stable/layers.html) といったところに軽量化され、誰でも使えるLambda Layerが公開されています。

**バージョンやランタイムの制限**

Lamdba Layerは作成する時にランタイムを指定して作成します（後述）。このバージョンやランタイムが、実際に作成するLambdaのバージョンやランタイムと異なると使用することができません。例えば、Windows環境で作成したLayerをアップロードしても、Amazon Linux上で動くLambda関数から使うことはできない、ということです。これが自宅にWindowsしかない方の場合に面倒な問題になるんですよね。でもご安心ください、私もWindows機しかありませんが、WSLを使わずにさくっとLayerを作ることは全然できます。この後、詳しく説明します。

## 2. Lambda Layerの作成手順

さて、いよいよLambda Layerを作成する手順です。大まかには以下の通りですが、いったん「こういう流れなんだな」と見てください。

1. 開発環境を用意する
2. 開発環境のPythonのバージョンをLambdaと揃える
3. Lambda Layer用のディレクトリを作成する。
4. 必要なライブラリやモジュールをインストールする。
5. ディレクトリをZIPファイルに圧縮する。
6. AWS LambdaコンソールからLambda Layerを作成する。

各手順について詳しく解説していきます。

### 2-1. 開発環境を用意する

自宅にMacやLinux機がある方、Windows上でWSL2環境を構築している方（そんな人はこの記事を見には来ないはずですが）は、ご自分の開発環境でそのまま以下の手順を実行すればOKです。

ただ、初心者のMacなどはよく分からずにインストールしてしまったAnacondaなどで環境がぐちゃぐちゃになっている可能性があります。Macユーザーでも自分のPCがどういう状態になっているのか自信のない方は、この下の手順に従って「きれいな」Python環境で作業することをおすすめします。

手元にLinux環境がない場合、一番手軽なのはAWS Cloud9を使う方法です。

1. AWSにログインしたら検索欄に「Cloud9」と入力し、検索結果から「Cloud9」を選択します。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/9369d228-6404-5737-f86d-4e1c22f78ad7.png)
    
2. 画面右側にある「環境を作成」という黄色のボタンをクリックして、新しいCloud9環境の作成に入ります。
2. 
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/6b149e73-d914-b3df-89e7-8f408a122ed8.png)
    
3. 次の画面で環境設定を行いますが、名前を入力する以外はデフォルトで大丈夫です。今回作るCloud9環境は使い捨てにするので、名称も適当でOK。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/328893fc-ed04-cf48-d14f-4161735c50d1.png)

4. 名称を決めたら画面右下の「作成」ボタンをクリックしてCloud9インスタンスが作成されるのを待ちましょう。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/809c8701-9ea7-39ff-954e-bea6e63efeed.png)

5. しばらくするとCloud9環境一覧の画面に画面が切り替わります。上部に表示されているステータスが青色から緑色に変わったら環境構築の完了です。「開く」と書かれたリンクをクリックしましょう。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/8cb35cf7-c1c5-5fa2-af5f-42020771a060.png)
    ↓
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/52e35948-3cf5-3a65-5f5a-ced7feafd1bd.png)
   
6. **注意：** 作成したCloud9環境を放置しておくと少額のストレージ料金が発生します。Layerの作成をそれほど頻繁に行わない、という場合はLayerの作成が終わったらCloud9環境を削除しておくことをおすすめします。削除の方法はCloud環境名の左側にあるラジオボタンをクリックし、「削除」ボタンをクリックします。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/556e0053-8898-dd73-260b-f4e6df67775a.png)
    
    表示されるダイアログボックスで下側にあるテキストボックスに”削除”と入力した上で、右下の「削除」ボタンをクリックします。    

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/a632c662-bddb-9402-48bb-ee38a3cb3607.png)

### 2-2. 開発環境のPythonのバージョンをLambdaと揃える

上の「1-2. 制限事項」でも述べた通り、Lambda Layerは実際のLambda関数とランタイムやバージョンを合わせる必要があります。

2024年3月末現在、Lambda関数のPython標準バージョンは3.12となっています。それで、Lambda Layerを作成する環境をPython3.12に合わせておきましょう。（多少のバージョン違いは問題なく動く場合もありますが、トラブルの元になるためおすすめしません）

以下はCloud9開発環境で解説しますが、Macなどでも基本的に操作方法は同じです。

1. まずはターミナルで以下のコマンドをと入力し、現在の開発環境のPythonバージョンを確認しましょう。Cloud9の場合は初期状態で画面下半分がターミナルとなっています。
    
    ```bash
    python3 —version
    ```
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/8c644f94-4488-f853-21eb-082f70399502.png)

    
2. 2024年3月末現在、標準のCloud9開発環境にインストールされているのはPython3.9です。これをPython3.12にアップグレードしていきます。
3. Pythonの複数バージョンをインストールする場合に必要なのが、pyenvというツールです。まずはこちらをインストールしていきます。以下のコマンドをターミナルに入力しましょう。
    
    ```bash
    git clone https://github.com/pyenv/pyenv.git ~/.pyenv
    ```
    
4. しばらく待つとpyenvのインストールが完了します。念のため以下のコマンドを入力して問題なくインストールできたことを確認します。
    
    ```bash
    ~/.pyenv/bin/pyenv --version
    ```
    
5. 以下のような表示になればインストールは完了しています。pyenvのバージョン番号は時期によって多少異なりますが、気にしなくてOKです。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/21909961-24de-7d20-8c4a-5cdfa7c089d6.png)
    
6. 続けてターミナルに以下のコマンドを1行ずつ、先頭の$を除いて入力します。（俗に「PATHを通す」と呼ばれる作業を行っています）
    
    ```bash
    echo 'export PATH="$HOME/.pyenv/bin:$PATH"' >> ~/.bashrc
    
    echo 'eval "$(pyenv init -)"' >> ~/.bashrc
    
    source ~/.bashrc
    ```
    
7. 「パスが通った」ことの確認として、ターミナルで以下の通り入力します。
    
    ```bash
    pyenv --version
    ```
    
8. 以下のようにpyenvのバージョンが表示されればOKです。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/f4b426fa-1901-db5b-063d-777d2c7dd8a4.png)
    
9. 次に、Python3.12に必要なモジュールをインストールします。ターミナルで以下の通り入力します。
    
    ```bash
    sudo yum -y install xz-devel
    ```
    
10. 下の画像のように`Complete!`というメッセージが表示されればOKです。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/335f3c5d-4bb4-9248-f5c7-b8899539ba6f.png)
    
11. いよいよPython3.12のインストールです。ターミナルで以下の通り入力します。
    
    ```bash
    pyenv install 3.12.0
    ```
    
12. インストールには数分かかります。下のように`Installed Python-3.12.0`と表示されればインストール完了です！
    
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/86d9bf1d-8320-a9db-5536-3ec8025426de.png)

13. 最後に、Pythonのバージョンを3.12に切り替えます。ターミナルで以下の通り入力します（先頭の$は除いて入力してください）。
    
    ```bash
    pyenv global 3.12.0
    ```
    
14. 以下のコマンドを入力して、表示が図のようになれば切り替え成功です。
    
    ```bash
    pyenv versions
    
    python --version
    ```
    
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/d8b330ff-f5d4-86bf-80be-9bd01f125e70.png)
    
15. 続いて、必要なライブラリのインストールに進みましょう。Lambda Layer用にライブラリをインストールする方法は通常とは少し異なるので、以下の手順に従ってください。

### 2-3. 必要なライブラリやモジュールをインストールする

1. Lambda Layer用にライブラリをインストールする際、専用のディレクトリを作成してそこにインストールする必要があります。まずはそのためのLambda Layer用ディレクトリを作成しましょう。以下のコマンドを入力してディレクトリを作成します。ターミナルのプロンプトが`ec2-user:~/environment/python $`となったらOKです。
    
    ```bash
    mkdir python && cd $_
    ```
    
2. 次に、Layerに必要なライブラリを`-t`オプション付きでインストールします。今回私はClaude3(Sonnet)をbedrock経由で使おうとboto3ライブラリのレイヤーを作成しました。みなさんは、`boto3`の部分を自分の必要なライブラリに置き換えてコマンドを実行してください。
    
    ```bash
    pip install boto3 -t .
    ```
    
3. 画面に`Successfully installed…`と表示があり、`ERROR`などの文字が表示されていなければインストールは完了です。（WARNINGは基本的に無視してOKです）
    
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/4cfce130-43f7-16d2-ee58-11d1f8ae9975.png)

### 2-5. ディレクトリをZIPファイルに圧縮してダウンロードする

1. 次に、インストールしたライブラリを手元のPCにダウンロードします。Cloud9画面の左側、ディレクトリツリーにある`python`ディレクトリを右クリックして、コンテキストメニューから`Download`を選択します。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/846cb9f2-cd80-886c-d827-23f8471051b8.png)
    
2. 名前を付けて保存ダイアログが表示されます。デフォルトの`python.zip`だと後で分からなくなるので、`ライブラリ名`+`Layer.zip`（例：OpenAILayer.zip）のように分かりやすい名前を付けておくのがおすすめです。

これでCloud9での作業は終了です。この後、Lambda Layerを追加して動作が問題ないことが確認できたら、ここで作成したCloud9環境は削除してOKです。

### 2-6. LambdaコンソールからLambda Layerを作成する。

この章では、AWS Lambdaコンソールを使ってLambda Layerを作成する方法について解説します。以下の手順に従って、Lambda Layerを作成していきます。

1. AWSマネジメントコンソールのサービス一覧から「Lambda」を選択します。
2. AWS Lambdaコンソールの左側のメニューから「レイヤー」を選択します。
3. 「レイヤーの作成」ボタンをクリックして、新しいLambda Layerの作成を開始します。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/144345f5-07f3-f18c-4b00-5c14e3120952.png)
    
4. レイヤー作成画面が表示されたら、以下の項目を入力します。
    1. 「名前」フィールドには、Lambda Layerの名前（自分の管理する他のレイヤーと重ならない名前が必要です）
    2. 「説明」フィールドは空白でも構いません。
    3. 「アップロード」ボタンをクリックし、先程Cloud9からダウンロードした「.zip」ファイルをアップロードします。
        
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/332120aa-c14f-0d40-adf6-bef9a91053c6.png)
        
    4. 「互換性のあるアーキテクチャ」フィールドでは`x86_64`にチェックを入れます。
        
    5. 「互換性のあるランタイム」フィールドをクリックし、`Python 3.12`を選択します。
        
    6. 最後に、右下の「作成」ボタンをクリックします。しばらくして、「レイヤー`boto3-1_34_65`のバージョン１が正常に作成されました。」のように表示されたらレイヤーの登録は完了です。
        
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/f881a5b6-1f5f-7069-8f51-1c980d83bc0e.png)

## 3. Lambda LayerをLambda関数に追加する

この章では、作成したLambda LayerをLambda関数に追加する方法について解説します。以下の手順に従って、Lambda Layerを関数にアタッチしましょう。

1. AWS Lambdaコンソール左側のメニューから「関数」を選択し、リストから関数を選択します。
2. 関数の編集画面が開かれたら、「レイヤー」セクションの右側にある「レイヤーの追加」ボタンをクリックします。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/2b419bb7-1024-8ce7-d4f1-f96bd56aa7e4.png)
    
3. レイヤー追加ウィンドウが開きます。「レイヤーを選択」セクションで「カスタムレイヤー」を選択し、その下のドロップダウンリストを開いて先ほど作成したレイヤーを選択します。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/c88177c5-7f46-4ba9-6d4b-32686ae50c50.png)

4. 「バージョン」ドロップダウンを開いて、「１」を選択します。
    1. レイヤーを修正するなどしてバージョンが変更されている場合は、ここで最新のバージョンを選択します。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/7ac5b384-99a9-f95e-df07-1fa081653fe8.png)
    
5. 「追加」ボタンをクリックして、選択したLambda Layerを関数にアタッチします。

これで、Lambda関数にLambda Layerを追加できました。関数をテスト実行してみて、Lambda Layerが正しくアタッチされたことを確認できたら作業完了です！

## 4. Lambda Layer作成についてのよくある質問

**Q: Python3.9～Python3.12まで１つのレイヤーで対応させることはできますか**

A: できますが、おすすめはしません。レイヤー作成時のPythonのバージョンを3.9にするなどしてレイヤーを作成すれば、とりあえずは動作するかもしれませんが、依存関係などの問題が発生する（そして原因究明に時間がかかる）リスクがあります。面倒でも、それぞれのバージョン用にレイヤーを作っておくのが安全です。

**Q: レイヤーの修正が必要になった場合はどうしたらいいですか**

A: レイヤーの修正が必要になった場合は、「ライブラリのインストール」の手順からもう一度実行しましょう。レイヤー作成時に何らかの問題があったと思われる場合は、「Cloud9開発環境の構築」からやり直して、きれいな環境でレイヤーを作るとより安全です。レイヤーをアップロードする際には、AWS Lambdaレイヤー コンソール画面から既存のレイヤーを選択し、新しく作成したzipファイルをアップロードすると、バージョン番号がインクリメントされて登録されます。その後、Lambda関数からレイヤーをアタッチする際に最新のバージョン番号を選択しましょう。

**Q: Lambda Layerの更新をLambda関数に適用するにはどうすればいいですか？**

A: Lambda Layerを更新した場合、関数に適用するには、関数の設定で新しいバージョンのLambda Layerをアタッチし直す必要があります。その後、関数を保存して変更を適用します。新しいバージョンのレイヤーが正しく機能することを確認するために、関数をテストしてください。

**Q: Lambda Layerを使うことで何かデメリットはありますか？**

A: Lambda Layerの読み込みには一定の時間がかかります。そのため、容量の大きなLayerをいくつもアタッチすると、Lambda関数のコールドスタートに影響がある（関数のレスポンスが遅くなる）可能性があります。ただし、一般的な用途ではほとんど気にならないレベルでしょう。もしパフォーマンスが問題になった場合は、できるだけシンプルな機能のLambda関数を作成したり、Layerのサイズ縮小をするなどしてコールドスタート時間の短縮を図ることができます。

**Q: 他の人が作成したLambda Layerを使うことはできますか**

A: 可能です。例えばPandasというライブラリは標準サイズだと重すぎるのですが、[https://aws-sdk-pandas.readthedocs.io/en/stable/layers.html](https://aws-sdk-pandas.readthedocs.io/en/stable/layers.html) といったところに有志が作成した（軽量化された）レイヤーが公開されています。これらのサードパーティー製レイヤーを使うには、Lambda関数からレイヤーをアタッチする際に、「ARNを指定」を選択し、下のテキストボックスでARNを指定することで利用できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664305/0cd2f144-ab60-7160-fc0a-36f1972bd245.png)

参考までに、私がCloud9で作成したPython3.12用のレイヤーのARNを貼っておきます。

|ライブラリ|ARN|
|----|--------------------------------------------------------------------|
| OpenAI | arn:aws:lambda:ap-northeast-1:027496193801:layer:openai_py312:1 |
| boto3(1.34.65) | arn:aws:lambda:ap-northeast-1:027496193801:layer:boto3-1_34_65:1 |



## 5. まとめ

AWS Lambda Layerは、Lambda関数の再利用性を高めるための重要なツールです。このドキュメントでは、初心者でもLambda Layerを作成する手順を解説しました。

サードパーティー製ライブラリをLambda Layer化できるようになると、Lambda開発の可能性が大きく広がります。また、Lambda関数の経験を積んでいくに連れて、自作のライブラリや共通コードをLayer化すれば、開発効率が大幅に向上します。

AWS Lambdaをより効率的に活用するために、ぜひLambda Layerを活用してみてください。