MacでLambdaレイヤーARMアーキを作成

# はじめに
　***arm64でLambda関数をデプロイせざるを得ないケースで、Layerを追加したい場合向け。*** imageデプロイを使えばどうとでもなるのだが、それは根本解決にはならない。前に一度やったのだが、やり方を失念してしまったため、備忘として記録する。
 Cloud9やEC2を使ってLayerを作成する方法もあるが、***AWSが提供するdocker imageを使えばローカル環境であらゆるLayerを作成できるし、インタラクティブにやりたい***ので、本記事ではその方法について記述する。

 # 環境
- 言語: python3.12
- OS: macOS Sonoma14.5
- RAM: 64GB
- Docker: 25.0.3

# 手順
この[Docs](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-layers.html#python-layer-compatibility)で推奨されている通り、Amazon Linuxベースコンテナイメージに基づくDocker環境に依存関係をインストールしてパッケージ化する。以下の手順の参考もとは[こちら](https://docs.aws.amazon.com/linux/al2023/ug/base-container.html)。

## Step.0
前提として、以下の点が満たされているか確認。
- ```ecr-public:GetAuthorizationToken```と```sts:GetServiceBearerToken```のアクションがIAMロールにアタッチ済み
- ```aws configure```の確認 (```--profile```オプションで指定も可)
- MacのDockerが起動している

## Step.1
まずは、DockerクライアントをAmazon Linuxパブリックレジストリに対して認証する。
```zsh
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws
```
```Login Succeeded```とコンソールに出ればOK。
```--profile```オプションをつける際は```--region```の後にでも書けば良い。ちなみに我らが```ap-northeast-1```は24年5月時点でサポートされていないのか、エラーとなる。

## Step.2
[こちら](https://gallery.ecr.aws/search)から欲しい環境のDocker imageを見つけて```docker pull```コマンドでコンテナイメージを取得する。今回はpython3.12が含まれるarm64アーキテクチャAWS SAMビルドイメージを用いる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409783/fd24a6e5-39f8-b1b3-1f94-8c6917aeea7c.png)
```public.ecr.aws/sam/build-python3.12:1-arm64```をpullする。
```zsh
docker pull public.ecr.aws/sam/build-python3.12:1-arm64
```
以下のような結果が出ればpullできている。
```zsh
Digest: sha256:629e2aeb90287ed1e16cc4b41740108d7a4b850c8aa36e047002e98964e73d87
Status: Downloaded newer image for public.ecr.aws/sam/build-python3.12:1-arm64
public.ecr.aws/sam/build-python3.12:1-arm64

What's Next?
  View a summary of image vulnerabilities and recommendations → docker scout quickview public.ecr.aws/sam/build-python3.12:1-arm64
```

## Step.3
コンテナをローカルで実行
```zsh
docker run -it --security-opt seccomp=unconfined public.ecr.aws/sam/build-python3.12:1-arm64 /bin/bash
```
一応、pythonのバージョンを確認
```zsh
bash-5.2# python --version
Python 3.12.3
```

## Step.4
Layerに入れたい必要なライブラリをインストールし、パッケージングする。まずはディレクトリの作成から。
```bash
mkdir -p layer/python/lib/python3.12/site-packages
```
このランタイムのレイヤーパスは決められているので、それに従う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409783/de7dd608-09cb-ae73-21ef-b4c23d96b5ca.png)

次に、上で作成したレイヤーパスをターゲットに指定して、pipで必要なライブラリをインストールする。今回は例としてpandasを入れる。
```bash
pip install pandas --target layer/python/lib/python3.12/site-packages
```
成功したら、```layer/python```を圧縮して```python.zip```というファイルを作る。
```bash
bash-5.2# cd layer/
bash-5.2# zip -r  ../python .
```
これでカレントディレクトリに```python.zip```というファイルが作成された。

## Step.5
作成した```python.zip```をローカルへコピーする。まずはターミナルでウィンドウを一つ増やして、今実行中のdockerコンテナのIDを取得する。
```zsh
inakason@buz ~ % docker ps
CONTAINER ID   IMAGE                                         COMMAND       CREATED          STATUS          PORTS     NAMES
0197d6a50aca   public.ecr.aws/sam/build-python3.12:1-arm64   "/bin/bash"   16 minutes ago   Up 16 minutes             gallant_raman
```
IDが確認できたら```docker cp```コマンドでコンテナからローカルへファイルをコピー
```zsh
inakason@buz ~ % docker cp 0197d6a50aca:/var/task/python.zip Desktop/python.zip
                               Successfully copied 45.5MB to /Users/inakason/Desktop/python.zip
```
コンテナ内のルートディレクトリ(?)が　```var/task/```だったので、先頭に追加することに注意する。dockerコンテナはここで用済みなので、```docker stop {ID}```で停止しておく。

## Step.6
後はマネジメントコンソールないしAWS CLIからLambda Layerを追加すれば良い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409783/b159115b-bed5-6327-ae17-2ac2ff6da182.png)
これで、```import pandas as pd```が走るようになる。

# おわりに
一つのLambda関数に追加できるLambda Layerの数と容量（確か、5つとデプロイサイズ含め250MB）の制約があるので、これを超えてしまう場合はimageや他AWSリソースの利用を検討しなければならない。