RIEを使ってLambdaコンテナイメージをローカルでエミュレートする

# はじめに
前回Lambdaコンテナイメージを、AWS以外のベースイメージから作る方法を記事にしました。

https://qiita.com/a_b_/items/337c4afee2e330efefe1

作成する際AWS Lambda Runtime Interface Emulator (RIE) を使って、ローカルでLambdaをエミュレートする方法を試しましたので記事にしました。


# 参考

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images-test.html

https://aws.amazon.com/jp/blogs/news/new-for-aws-lambda-container-image-support/

# やったこと
前回同様に、プロジェクトのディレクトリを作成し、Pythonのファイルを作成します。
Dockerfileは、エミュレータを含めるかどうかで記述が変わりますので、ここではファイルを作成するだけです。
```bash
# プロジェクトディレクトリ作成
mkdir sample-ecr-lambda
cd sample-ecr-lambda

# リージョンとアカウントIDを環境変数にセット
REGION="ap-northeast-1"
ACCOUNTID=$(aws sts get-caller-identity --output text --query Account)

# Dockerfile作成
## エミュレーターを組み込む/組み込まないで内容が異なるので、まだ記述しない
touch Dockerfile

# pythonファイル作成
touch app.py
```
```python:app.py
import json

def handler(event, context):
    return {
        "statusCode": 200,
        "body": json.dumps(
            {
                "message": "hello world",
            }
        ),
    }
```

次に、RIEをダウンロードします。

```bash
mkdir aws-lambda-rie

curl -Lo aws-lambda-rie/aws-lambda-rie \
 https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie

chmod +x aws-lambda-rie/aws-lambda-rie
```

## RIEをイメージに組み込む場合
公式の説明は以下になります。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images-test.html#images-test-alternative

エントリポイントに指定するスクリプトファイルを記載します。
AWS_LAMBDA_RUNTIME_API 環境変数の有無で、RICを使うか、RIEでエミュレートするかに分かれます。

```bash
touch entry_script.sh
# 実行権限も付与
chmod +x entry_script.sh
```
```bash:entry_script.sh
#!/bin/sh
if [ -z "${AWS_LAMBDA_RUNTIME_API}" ]; then
  exec /usr/bin/aws-lambda-rie /usr/bin/python3 -m awslambdaric $@
else
  exec /usr/bin/python3 -m awslambdaric $@
fi
```

Dockerfileを作ります。前回のものとは異なり、エントリポイントに上記ファイルを指定しています。

```Dockerfile:Dockerfile
FROM ubuntu:20.04

RUN apt-get update && apt-get install -y python3-pip

RUN mkdir /function && \
  pip install --target /function awslambdaric
  
COPY app.py /function/

COPY ./entry_script.sh /entry_script.sh
ADD ./aws-lambda-rie/aws-lambda-rie /usr/bin/aws-lambda-rie

WORKDIR /function

ENTRYPOINT [ "/entry_script.sh" ]

CMD [ "app.handler" ]
```

後はBuildして動かすだけです。
```bash
# Build
docker build -t func1 .

# コンテナ実行
docker run --rm -p 9000:8080 func1:latest

# テスト
## 別のターミナルから
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'

# 終了
## docker runしたターミナルで
Ctrl+C
```

## RIEを組み込まない場合
少しでもイメージを小さくしたい場合は、こちらのほうがいいかもしれません。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images-test.html#images-test-add

Dockerファイルの中身は前回と同じものです。
```Dockerfile
FROM ubuntu:20.04

RUN apt-get update && apt-get install -y python3-pip

RUN mkdir /function && \
  pip install --target /function awslambdaric
  
COPY app.py /function/

WORKDIR /function

ENTRYPOINT [ "/usr/bin/python3", "-m", "awslambdaric" ]

CMD [ "app.handler" ]
```

Buildします
```bash
# Build
docker build -t func1 .
```

RIEは、コンテナ実行時に、RIEがあるディレクトリをマウントして使用します。詳細は以下のページにあります。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images-test.html#images-test-add


```bash
docker run --rm -p 9000:8080 \
 -v `pwd`/aws-lambda-rie:/aws-lambda \
 --entrypoint /aws-lambda/aws-lambda-rie \
 func1:latest \
 /usr/bin/python3 -m awslambdaric app.handler
```
- 2行目：ローカルのRIEファイルがあるディレクトリをマウント
- 3行目：（マウントしたため、コンテナ内部で実行可能な）RIEファイルをエントリポイントに指定
- 5行目：3行目に与える引数

となります。

あとは同じようにテストです。
```bash
# 別のターミナルから
$ curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'

# docker runしたターミナルで
Ctrl+C
```

問題なければ、依然と同様にECRにPUSHして、Lambda作成に進みます。

https://qiita.com/a_b_/items/d9398fd6efe0f66b6c6f#ecr%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E4%BD%9C%E6%88%90%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8push

# おわりに

今回はRIEの使い方を記事にしました。
ベースイメージを自分で選んだものにしても、RIEを用いれば簡単にローカルでLambdaをエミュレートできるため、開発の敷居はかなり下がったと感じました。