Lambdaで絶対にエラーならないレイヤーの作成方法

# 背景
Lambda関数でS3のファイルをSFTPサーバへ転送したいです。調べたところ、paramikoライブラリーの利用を決めたより、Lambdaのparamikoレイヤーを作成する必要があります。

# 現象
requestsライブラリーなどのレイヤーを作成した方法のように、「`pip install paramiko .`」コマンドを使って、ライブラリーをインストールして、Zipファイルを圧縮して、レイヤーを作成しても、関数でparamikoを使う時にエラーになります。
原因を推測すると、paramiko自分自身の依頼が複雑で依頼しているライブラリーはLambdaの後ろに存在するEC2サーバ上にはインストールしてないかと思っていますね。なせならば、コマンドを実行する端末環境はLambda後ろのEC2サーバと違うでしょう。

# 解決方法

### １、ローカルにDocker をインストールする

[Docker Download and install](https://docs.docker.com/desktop/#download-and-install)を参照してください

#### ２、適切なディレクトリ構造を作成する

##### ①下記のフォルダ構成を作る
もし複数なランタイムの互換性が必要であれば`python3.6`などのフォルダーも作成して、ライブラリーのインストールコマンドを実行してください

```shell
├── requirements.txt
└── python/
    └── lib/
      ##├── python3.6/
      ##│   └── site-packages/
        └── python3.9/
            └── site-packages/
````

##### ②requirements.txtにライブラリーを記入する
バージョンをしてしないままであればランタイムにてサポートしている最新のバージョンをインストールされます。もしバージョンをしていた場合　[Requirements File Format](https://pip.pypa.io/en/stable/reference/requirements-file-format/)　を参照してください

```
paramiko
```

#### ３、ライブラリインストールコマンドを実行する
##### ①ライブラリーをインストールする
下記のコマンドを実行すると、PythonランタイムバージョンによりDockerイマージがダウンロードして起動します、そして`paramiko`ライブラリーをフォルダーインストールされます。

```shell
docker run -v "$PWD":/var/task "public.ecr.aws/sam/build-python3.9" /bin/sh -c "pip install -r requirements.txt -t python/lib/python3.9/site-packages/; exit"
```

##### ②Zipファイルを作成する
```shell
zip -r paramiko-layer.zip python > /dev/null
```

#### ４、Lambdaレイヤーを作成する
マネージメントコンソール或いはCLIでLambdaレイヤーを作成します。
```shell
aws lambda publish-layer-version --layer-name paramiko-layer --description "Paramiko layer libs." --zip-file fileb://paramiko-layer.zip --compatible-architectures "arm64" --compatible-runtimes "python3.9" #"python3.6"
```

# 注意点
自分がM1チップのMacbookPro端末しか持っていません、なので「Mac with Apple chip」のDockerしかインストールできません。
paramikoレイヤーを作成した時、アーキテクチャは`x86_64`に指定すると関数を実行したらエラーになりました。レイヤーを`arm64`に指定しても関数を`x86_64`に指定したらエラーになりました。
要は、**<font color="DeepPink">Dockerのアーキテクチャ、Lambdaレイヤーのアーキテクチャ、関数のアーキテクチャがイコールの必要があります。</font>**


# 他の方法
上記の方法がおすすめなんですが、AWSオフィシャルではAWS CLIコマンドでレイヤーを作成する方法もあります。カスタマイズなどが上記の方法よりは弱いと言われますが、一旦試て作成ができました。
### 1、AWS SAMをインストールする
##### ①aws samをインストールする
```shell
brew tap aws/tap
brew install aws-sam-cli
```
##### ②インストールを検証する
```shell
sam --version
SAM CLI, version 1.46.0
```
### ２、適切なディレクトリ構造を作成する
##### ①下記のフォルダー構成を作成して`requirements.txt`に上記と同じ方法でライブラリー名を記入する。
```shell
├── paramiko-layer
│   └── requirements.txt
└── template.yaml
```
##### ②templateファイルを下記の内容を記入する
```yaml
Resources:
  ParamikoLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      ContentUri: 'my_layer/'
      CompatibleRuntimes:
        - python3.9
      CompatibleArchitectures:
        - arm64
    Metadata:
      BuildMethod: python3.9
```

### ３、レイヤー作成コマンドを実行する
```shell
sam build ParamikoLayer
```
下記のようなアウトプットがあれば作成成功です。
```shell
Building layer 'ParamikoLayer'
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
[*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
[*] Deploy: sam deploy --guided
```

Zipファイルの作りや、Lambdaレイヤーの作成などは上記と同じです。