Lambda関数をコンテナイメージで動かしてみた

# はじめに
この記事は [BeeX Advent Calendar 2020](https://qiita.com/advent-calendar/2020/beex) の12/6の記事です。

==

今年のre:InventでLambdaがコンテナイメージをサポートしたと発表がありました。

* [AWS Lambdaがコンテナイメージのサポート](https://aws.amazon.com/jp/blogs/aws/new-for-aws-lambda-container-image-support/)

前に以下の記事で書きましたが、Lambdaで外部ライブラリを使用したい場合はLambda Layerに別途アップロードが必要でした。
今回発表されたコンテナを使うことで、その部分が簡略化できないか試してみます。
[Lambda Layerに外部のライブラリをアップロードする](https://www.capybara-engineer.com/entry/2020/06/18/160458)

尚、Dockerはほとんど使ったことないので初心者レベルです。

# 環境
PC：Windows 10
Docker：Docker version 19.03.13, build 4484c46d9d

# 前提
* Dockerの初期設定は完了済み
* Python3はインストール済み(Lambdaランタイムと同じかそれ以上)
* AWSアカウントは作成済み
* Amazon ECRリポジトリは未作成

# 実際の操作
## requirements.txtファイルの作成
ローカルで以下のコマンドを実行し、requirements.txtファイルを作成します。

```
$ pip install dataclasses==0.6
$ pip install dataclasses_json==0.5.2
$ pip freeze > requirements.txt
```

## lambda functionの作成
作成済みのLambdaからコードをコピーし、ローカルに作成します。

```lambda_function.py
import json
from dataclasses import dataclass
from dataclasses_json import dataclass_json

@dataclass_json
@dataclass
class TestColumns:
    column1: str = None
    column2: str = None
    column3: str = None
    
def exec_function(event):
    column_list = TestColumns()
    column_list.column1 = "hoge"
    column_list.column2 = "huga"
    column_list.column3 = "hogehuga"

    print(column_list)
    column_list_json = column_list.to_json(indent=4)
    print(column_list_json)

def lambda_handler(event, context):
    exec_function(event)
```

## DockerFileの作成
次にDockerFileを作成します。
イメージは公式が提供しているものを使用しています。
※DockerfileのFが大文字になってて地味に引っかかりました

```Dockerfile
FROM amazon/aws-lambda-python:3.7

COPY requirements.txt lambda_function.py ./
RUN pip install --no-cache-dir -r requirements.txt

CMD [ "lambda_function.lambda_handler" ]
```

## イメージをBuildする
以下のコマンドを実行して、イメージをビルドします。

```
$ cd [DockerFile格納先DIR]
$ docker build -t lambda-container-dataclass .
```

イメージが作成されたことを確認します。

```
$ docker images
REPOSITORY                                     TAG                 IMAGE ID            CREATED             SIZE
lambda-container-dataclass                     latest              0655a0bf775a        40 seconds ago      892MB
```

## ECRリポジトリへのPush
AWSコンソールからECRリポジトリを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/fdc50497-5779-b02a-6f3c-af833eb1797f.png)

以下のコマンドで作成したECRリポジトリにイメージをPushします。

```
$ docker tag lambda-container-dataclass:latest XXXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-container-dataclass
$ docker images
REPOSITORY                                                                     TAG                 IMAGE ID            CREATED             SIZE
XXXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-container-dataclass   latest              0655a0bf775a        41 minutes ago      892MB
```

```
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin XXXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com
Login Succeeded
```

```
$ docker push XXXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-container-dataclass:latest
The push refers to repository [XXXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-container-dataclass]
2cbe32b34b1c: Pushed
1f6657a679d9: Pushed
069cd8bd11dd: Pushed
6e191121f7ea: Pushed
d6fa53d6caa6: Pushed
1fb474cee41c: Pushed
b1754cf6954d: Pushed
464c816a7003: Pushed
latest: digest: sha256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX size: 1997
```

無事にアップロードできました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/9cdac978-2a7f-1828-acf4-5aa2f4a394bf.png)

## Lambda作成・実行
Lambda関数の作成からコンテナイメージを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/5ec0e532-0a90-0fa4-63d3-7929b66b705e.png)

先ほどPushしたECRのイメージを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/10838d7a-6a54-9ba0-ad96-1398af7c8351.png)

今回は実行ロールを新しく作成するように選択して、関数の作成を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/3080b1a1-7a53-dc62-ac6c-706d18070522.png)

Lambdaが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/58da546d-8da9-b269-c60d-e57f3c25fe0d.png)

今までコードが表示されていた部分はイメージに変わっています。それ以外は特に変更なさそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/3ef1c4ed-cede-cdb5-e3f4-b15306516dfe.png)

## 実行結果確認
コンソールから実行したところ、問題なく正常終了しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/d06a533b-7140-7a26-80a8-7b641cb7a232.png)

出力内容も問題なさそうです。

```
START RequestId: 62d1c78f-b14a-4358-babc-e24a1ededcab Version: $LATEST
TestColumns(column1='hoge', column2='huga', column3='hogehuga')
{
    "column1": "hoge",
    "column2": "huga",
    "column3": "hogehuga"
}
END RequestId: 62d1c78f-b14a-4358-babc-e24a1ededcab
REPORT RequestId: 62d1c78f-b14a-4358-babc-e24a1ededcab	Duration: 18.50 ms	Billed Duration: 1007 ms	Memory Size: 128 MB	Max Memory Used: 52 MB	Init Duration: 987.64 ms	
```

元々のLambda関数で出力した内容と見比べても特に差分はないので大丈夫そうです。

```
START RequestId: 6054e059-68ca-451f-a4f1-13804f24b8d8 Version: $LATEST
TestColumns(column1='hoge', column2='huga', column3='hogehuga')
{
    "column1": "hoge",
    "column2": "huga",
    "column3": "hogehuga"
}
END RequestId: 6054e059-68ca-451f-a4f1-13804f24b8d8
REPORT RequestId: 6054e059-68ca-451f-a4f1-13804f24b8d8	Duration: 1.72 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 54 MB	Init Duration: 194.92 ms	
```

# さいごに
ということで、今まで外部レイヤー追加したりSAMで設定したりしていましたが、今回のコンテナを活用することでデプロイをシンプルにLambdaを実行することができました。

ローカルでの開発もしやすくなると思いますし、今後どんどん使われる機能ではないかと思います。

# 参考
* [AWS Lambdaがコンテナをサポートしたのでちょっと試してみた](https://www.keisuke69.net/entry/2020/12/02/051538)
* [【Dockerコマンド】イメージ作成からコンテナ起動までの流れを紹介！](https://kitsune.blog/docker-command)
* [AWS CLIを使ってECRにDockerイメージを登録する](https://dev.classmethod.jp/articles/push-docker-image-to-ecr-with-cli/#%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E4%BD%9C%E6%88%90)