【AWS】AWS Lambdaで外部モジュール（ライブラリ）を含むPythonをzipデブロイする方法

## 背景
- [AWS Lambda](https://aws.amazon.com/jp/lambda/)で`Python`を実行する際、[pandas](https://pandas.pydata.org/)などの外部ライブラリは`Lambda`に事前に`install`されていないため、いずれかの方法で`Lambda`に外部ライブラリ等を`install`させる必要があります。
- 私が知る限りでは、[AWS Lambda](https://aws.amazon.com/jp/lambda/)で`Python`を実行する際に、外部ライブラリを使用できるようにする方法は以下の3つです。
    1. [Lambda レイヤー](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-layers.html)を使用する方法。
    2. [zip デブロイ](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-package.html)を用いる方法。
    3. [コンテナイメージデブロイ](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-image.html)を用いる方法。
- それぞれの方法にメリット・デメリットがありますが、今回は、最もよく使用されているであろう「 2. [zip デブロイ](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-package.html)を用いる方法。」についてご紹介します。

## 目標
- 外部ライブラリを含む`Python code`を`zip`デブロイ方式によって、[AWS Lambda](https://aws.amazon.com/jp/lambda/)で関数を実行できるようになる。

## [AWS Lambda](https://aws.amazon.com/jp/lambda/)とは
- 本題に入る前に、[AWS Lambda](https://aws.amazon.com/jp/lambda/)というサービスについて少しご紹介します。
- なお、ここの解説は私の脳みその記憶ベースで記載していることにご留意ください。
- [AWS Lambda](https://aws.amazon.com/jp/lambda/)はAWSの代表的なサーバーレスサービスの一つで、サーバーを構築することなく手軽にプログラムを動かすことができるサービスとして知られています。
- 様々な用途に使用できるサービスですが、よく使用される方法の一つとしては、[Amazon API Gateway](https://aws.amazon.com/jp/api-gateway/)をトリガーとしてAPIサービスを構築するのに使用されたりします。
- APIなどの必要な時にちょっことプログラムが動けば良いようなサービスの場合は、[AWS Lambda](https://aws.amazon.com/jp/lambda/)を使用することにより、[Amazon EC2](https://aws.amazon.com/jp/ec2/)などを使用してずっとサーバーを起動させているよりサーバーコストが安くなるなどのメリットがあります。
- また、今回の内容につながりますが、[AWS Lambda](https://aws.amazon.com/jp/lambda/)を支える裏側の技術はコンテナ仮想化技術を使用しています。
- そのため、実行時におそらく`Amazon linux`をベースとしたイメージを用いたコンテナで処理が実行されているため、外部ライブラリを使用する際は何かしらの方法で外部ライブラリデータを[AWS Lambda](https://aws.amazon.com/jp/lambda/)に渡す必要があります。
- 今回ご紹介する方法は、`zip`ファイルに外部ライブラリのデータも含ませておくことにより、`Python`関数で外部ライブラリ等も`import`して使用できるようにする方法になります。

## デブロイするzipファイルを作成するDocker環境の構築
- 今回のデブロイ方法は、AWSのLambda公式ページでは[.zip ファイルアーカイブで Python Lambda 関数をデプロイする](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-package.html)のページの「依存関係のあるデプロイパッケージ」の項目に該当します。
- 公式ページでは、ローカル環境で`zip`ファイルを作成していましたが、私は`Docker`信者（`Docker`ならどんな環境でも動くから安心と信じてるマン、私の造語です。）ですので、今回は`Docker`で`zip`ファイルを作成する環境作成からご紹介します。
- 下記の`github`リポジトリをクーロンもしくはDLしていただき、`$docker-compose up --build`で`Python`を実行できるコンテナを立ち上げます。

https://github.com/takuma-competition/docker-python-lambda-zip-use

- 下記の記事を参考に立ち上げたコンテナ内部に`VS Code`で入ります。
- 続きの解説は、「小ネタ：コンテナのルートディレクトリでフォルダを開く方法」まで実施した想定で進めています。

https://qiita.com/takuma-1234/items/822823ce151340945975

## VS Codeを使用してDocker環境でデブロイ用のzipファイルを作成する方法
- コンテナに接続した`VS Code`でターミナルを開きます。

![01_lambda_zip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/73ab5c4f-c69e-9966-c4d1-3a0a7ced349e.png)


- `$cd workdir`で`workdir`ディレクトリに移動します。

![02_lambda_zip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/1814a8cb-a9a4-75d5-9ed3-eb1f8316473d.png)


- `$mkdir`コマンドで、新しいディレクトリを作成します。
```bash:
$mkdir zip_lambda_deploy
```
- `$cd`コマンドで、新しいディレクトリに移動します。
```bash:
$cd zip_lambda_deploy
```
- `$touch`コマンドで新しい`py`ファイルを作成します。
```bash:
$touch lambda_function.py
```
- `$touch`コマンドで新しい`txt`ファイルを作成します。
```bash:
$touch requirements.txt
```
- `lambda_function.py`に以下の`code`を記載します。

```python:lambda_function.py
#はじめにimportの検索pathを追加するcodeを記載する。
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), './packages'))

import requests
def lambda_handler(event, context):   
    response = requests.get("https://www.example.com/")
    print(response.text)
    return response.text
```
- ここまでのコマンドと`lambda_function.py`を記載した`VS Code`画面
![03_lambda_zip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/e7fbda29-0c77-189a-54b6-f7b042bc06a2.png)

- `requirements.txt`に必要な外部ライブラリ名を記載します。
ここでは、`requests`が必要なので、`requests`を記載しています。

```txt:requirements.txt
requests==2.28.2
```

- 必要なライブラリを`pip`で`install`します。

```bash:
#requirements.txtを使用して一気にinstall
$pip install --target ./packages -r requirements.txt

#補足：ライブラリ名を個別に指定してinstallする方法
$pip install --target ./packages requests
```

- `zip`コマンドでライブラリごとzip化します。
```bash:
$zip -r ../zip_lambda_deploy .
```

![04_lambda_zip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/3fee5d4d-c99e-1bee-6983-93293cf44d78.png)


### Lmabdaにzipデブロイを行う方法
- 最後に作成した`zip`ファイルを`Lmabda`にデブロイします。

### AWSのコンソール画面から「Lmabda」のコンソール画面に移動します。
![05_lambda_zip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/412344a4-1163-a07b-cee6-63c91f5b116d.png)

### サイドバーから「関数」をクリックしてから、「関数の作成」をクリックします。
- 「関数」ボタンが表示されていない場合は、左側の3本のバーをクリックしてくるとサイドバーが表示されます。
![06_lambda_zip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/050537b2-a670-4a43-4698-8176c13859f0.png)

### Lmabda関数を「一から作成」で作成します。
1. ここでは、「関数名」は`zip_lambda`とします。
2. 「ランタイム」は`Python3.9`を選択します。
3. 「アーキテクチャ」は`zip`ファイルを作成した環境に合わせて選択してください。
なお、[docker-python-lambda-zip-use](https://github.com/takuma-competition/docker-python-lambda-zip-use)からクローンした`dockerfile`を用いて、ここまで解説通りに進めてきた方は`x86_64`を選択して進めてください。
![07_lambda_zip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/18c63c65-b047-e2ce-a499-f542e0512543.png)

### 「アップロード元」をクリックし、選択肢から「.zipファイル」を選択します。
![08_lambda_zip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/303e483c-5c9b-0fdd-df92-1e061754d441.png)

### 「アップロード」をクリックし、先ほど作成した`zip_lambda_deploy.zip`を選択し「保存」をクリックして`zip`ファイルを`Lambda`にアップロードします。
![09_lambda_zip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/a5578d98-9e6a-8be7-42ca-9f47c6badb20.png)

### 「テスト」タブをクリックします。
![10_lambda_zip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/f63675ac-28bb-4ece-6be4-3391ceed2263.png)

### 「テスト」をクリックし`Lmabda`関数を実行します。
![11_lambda_zip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/b0817191-9a6d-af4f-58af-487bc05c0c16.png)

### 「詳細」を開き、ログにHTMLが記載されていれば成功です。
![12_lambda_zip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/5a621eea-f2e1-a032-81f1-336acb822617.png)

## 参考資料
https://aws.amazon.com/jp/lambda/

https://pandas.pydata.org/

https://aws.amazon.com/jp/lambda/

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-layers.html

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-package.html

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-image.html

https://aws.amazon.com/jp/api-gateway/

https://aws.amazon.com/jp/ec2/

## 個人ブログ

https://takuma-tech.com/2023/03/07/395/