【Lambda】pythonの外部モジュールをS3経由で取り入れてみた

# 概要
lambdaを使ってdisny監視botを作る際にlambdaを使って定期実行したかったのでawsのlambdaを使うことにした。
この際に、line-sdk-botをlambdaに取り入れる必要があったのでその方法を記す。

※lambdaを初めて触るため間違っているところがあったら指摘ください。

# ローカルの設定
まずはdocker-lambdaディレクトリを作成する。

```
mkdir docker-lambda
cd docker-lambda
```

ディレクトリの構造は以下。

docker-lambda
├── Dockerfile
├── deploy.sh
└── requirements.txt

それぞれのファイルは以下のように構成する。

Dockerfileは以下。

```:Dockerfile
FROM lambci/lambda:build-python3.7
ENV AWS_DEFAULT_REGION ap-northeast-1

ADD . .

CMD pip install -r requirements.txt -t python/lib/python3.7/site-packages/ && \
    zip -r linetest.zip ./python 
```

lambdaではline-bot-sdk、pandas、numpy、requests、boto3を入れたかったので以下のようにrequirements.txtを作成。

```:requirements.txt
line-bot-sdk
pandas
numpy
requests
boto3
```

最後に実行用にshファイルは以下のように構成する。
`docker build -t lambda_test .`
に関しては一度imageを作成してしまったらコメントアウトシてしまって構わない。

```:deploy.sh
# 初回のみ コンテナの立ち上げ
docker build -t lambda_test .
# コンテナの実行
docker run -v "$PWD":/var/task lambda_test
#　権限の付与(lambdaで読み込ができるようにする)
chmod -R 755 ./*
```

それぞれのファイルが作成し終わったら、ターミナルで以下を実行する。

```:terminal
sh deploy.sh
```

```:output
 adding: python/lib/python3.7/site-packages/urllib3-1.26.2.dist-info/RECORD (deflated 62%)
 adding: python/lib/python3.7/site-packages/urllib3-1.26.2.dist-info/WHEEL (deflated 14%)
 adding: python/lib/python3.7/site-packages/urllib3-1.26.2.dist-info/top_level.txt (stored 0%)
```

このように実行が完了すると、pythonというフォルダとlinetest.zipというzipファイルが完成する。
ここでlinetest.zipはpythonをzip化したものである。
作成されたzipファイルをlambdaのレイヤーとして取り入れることで外部モジュールを使用可能になる。

```:ls
Dockerfile              lambda_function.py      python
deploy.sh               linetest.zip            requirements.txt
```

# レイヤーの作成

awsのコンソールに行き、lambda→レイヤー→レイヤーの作成　で選択する。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/a5d1928c-82a1-fec4-6d14-68a0b9e97492.png)

名前:好きなレイヤー名(後で何のためのレイヤーかわかるように)
説明:どんなモジュールが入っているかなどの説明を書く
upload:<=10MB→zipファイルをアップロード
　　　 　>10MB→s3経由でアップロード
ランタイム:今回はpython3.7を選択
ライセンス:何も書かなくて良い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/6d52dc67-1414-6858-d7d9-da099851dd68.png)

今回はzipファイルのサイズが10MBを超えるため、S3を経由してzipファイルをアップロードする。

サービス→s3→バケットを作成

バケット名:何でも良い
リージョン:lambdaにあわせる(今回は東京で統一)
パケット設定:全てブロック
パケットのバージョニング:無効にする
デフォルトの暗号化:無効にする
詳細設定:変更なし

↓
バケットの作成

![FireShot Capture 109 - S3 Management Console - s3.console.aws.amazon.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/f12351d5-76aa-d414-2bff-cd9a03d1c50f.png)

バケットが作成できたら、作成したバケットを選択。(今回はpypy-testというパケットを作成)
アップロード→ファイルを追加→先程作成したzipファイルをアップロード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/805c1817-1d70-4bef-590d-3aa6712d3507.png)

アップロードしたzipファイルを選択するとオブジェクトURLを見れるのでこれをコピーしておく。

再びlambdaに戻り、レイヤーを選択。
アップロードのところにオブジェクトURLを貼り付ける。

# 関数の作成

lambda→関数→関数の追加

作り方:一から作成
関数名:適当
ランタイム:python3.7
↓
関数の作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/3f8229d2-5a8b-9215-b156-c72db302aaf1.png)



## ここでハマったこと

リージョンが東京じゃないとs3が使えないので注意。
初めは北アフリカとかになってたはず。。。

![lamnda.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/d7a386db-ae1d-f12f-380d-447141884271.png)


関数を選択し、レイヤーの追加を選択。
カスタムレイヤーを選択し、作成したレイヤーを選択し、追加をクリックする。
(ここで作成したレイヤーが表示されない場合、ランタイムがあっていない可能性があるので確認する。)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/f81af575-0eee-4dfd-794b-d9fc95a74229.png)

最後にテスト用にAPI Gatewayの設定をする。
トリガーを選択→API Gateway→APIを作成する→HTTP API→セキュリティ:オープン→追加


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/67b3b310-6212-533e-98b0-c10e65112f51.png)

今回はテスト用にnumpyが使用できるか確認する。
以下のようにlambdaのコードを書き換える。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/7b583959-263b-0458-c043-83fa7e6673ab.png)

テストを選択して、実行が成功することを確認する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/81ef1fee-d719-4e27-44ee-0f2dbe010085.png)

API Gatewayを選択し、APIエンドポイントからurlにジャンプすると、以下のようにsin(1)の結果が帰ってきているのが確認できる。

![FireShot Capture 115 - disny - Lambda - ap-northeast-1.console.aws.amazon.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/a340277d-ae62-3f74-8a3f-e5235f0a6cf3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/b05f6135-b8c8-bf80-d1a5-920c589328d9.png)


次回以降これを応用してlinebotを作成する。






# 参考記事
・[chmodの設定](https://qiita.com/ntkgcj/items/6450e25c5564ccaa1b95)

・[lambdaのローカルの設定について](https://qiita.com/i35_267/items/15b981acae8cf7c763ae)

・[lambdaにpythonのモジュールをuploadする方法](https://www.suzu6.net/posts/83-lambda-zip/)