AWS Lambda Runtime Interface EmulatorをDocker Desktop for M1で試してみる

こんにちは、toyohamaです :birthday:
実はクリスマスっぽい別のネタを用意してたんですが、いざ手をつけようとしたときに、ふと「なんかこれ、かぶりそうだな……」と思ったので、急遽タイトルのようなネタにしてみました。

## 今回使うもの
### M1 Mac

M1 MacBook Airをこないだ買いました。１ヶ月ほど使った感想ですが、ハードウェアアーキテクチャ含めてIntel MacよりiPadに近い感じがします。
今回の記事のためにDocker入れたりなんだかんだインストールしたりしましたが、特に熱くなることもなく動作がもっさりすることも皆無でとても快適です。

### AWS Lambda Runtime Interface Emulator
略して`RIE`です。
[これとか](https://www.publickey1.jp/blog/20/aws_lambdaaws_reinvent_2021.html)、[これとか](https://aws.amazon.com/jp/blogs/news/new-for-aws-lambda-container-image-support/)、詳しくはネットで記事を参照いただければとおもいますが、

- AWS Lambdaでコンテナ起動できるようになった
- なんと10GBのイメージまでOK
- そんな重たいイメージいちいち検証のためにアップしてられないから、Emulatorが用意された(んだと思う)

ということで、手元のマシンでそのコンテナがLambdaから起動できるかテストができる、というのがRIEです。

### Docker Desktop for M1
みなさんはDocker好きですか？　わたしは大好きです。
いまや私物の開発環境も全てDockerで構築してます。別にVMでもかまわんと思うのですが、なんでこんなに惹かれるんですかね。FreeBSDのjailに感覚が似てるからかもしれません(個人の感想です)。

M1 Macの正式対応は2021年2月との噂ですが、思ったよりも早く[プレビュー版のDocker Desktopが登場](https://www.publickey1.jp/blog/20/applem1docker_desktopwsl2gpu.html)し、かつ登録とか申請なしで[ダウンロード](https://www.docker.com/blog/download-and-try-the-tech-preview-of-docker-desktop-for-m1/)もできるようになりました。

### というわけで
これらを組み合わせて、きちんと動くのかを試してみました。あれがないこれがないってきっと色々いわれて投げ出しそうになるんだろうな。。と思いつつ。

## インストール

### Docker Desktop For M1
dmgを開くとこんな感じです。`AppleSilicon-Preview7`というバージョンです。
![スクリーンショット 2020-12-21 23.42.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102801/c27c08e6-5720-b4e6-1b00-535a0f1ac598.png)

でたー！このPREVIEWの文字を一度みてみたかったんですよね……と、一瞬テンションをあげながらドラッグ&ドロップ。
![スクリーンショット 2020-12-21 23.42.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102801/28709f96-2fd1-2ee2-d1f0-c73687d69269.png)

初回の起動はなぜか`Docker Desktop is runnning`にならず、いちどRestartしましたが、そのあとは普通に動いています。

### AWS Lambda Runtime Interface Emulator

[AWSの公式](https://github.com/aws/aws-lambda-runtime-interface-emulator/)が参考になるかと思います。`aws-lambda-rie`ってバイナリを指定のディレクトリにコピってくるだけなんで特に問題ないかと。

```
 $ mkdir -p ~/.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
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   164  100   164    0     0    315      0 --:--:-- --:--:-- --:--:--   314
100   640  100   640    0     0    688      0 --:--:-- --:--:-- --:--:--   688
100 7964k  100 7964k    0     0  1230k      0  0:00:06  0:00:06 --:--:-- 1910k


 ~/.aws-lambda-rie $ ls -la
total 17120
drwxr-xr-x   3 toyohama  staff       96 12 21 23:19 .
drwxr-xr-x+ 15 toyohama  staff      480 12 21 23:19 ..
-rwxr-xr-x   1 toyohama  staff  8155136 12 21 23:19 aws-lambda-rie
```
## サンプルの作成

### Dockerfile
```
FROM public.ecr.aws/lambda/python:3.8

COPY app.py ${LAMBDA_TASK_ROOT}

CMD ["app.lambda_handler"]
```
AWSが提供するDockerイメージにはRIEが標準で入ってるため、検証用のエントリポイントが内包されているみたいです。てことは、さっきインストールしたRIEは何か意味があったのかな？　と思いつつ作業を進めます。

### app.py
```
def lambda_handler(event, context):
  message = "recieved data is {}".format(event['q'])
  return { 
    'message' : message
  }  
```

激簡単な内容ですが、とりあえず投げたデータがちゃんと返ってくるかぐらいは確認しようと思いました。Pythonを選んだ深い意味はありません。

### コンテナビルド
```
 $ docker build -t rie_python/latest .                        
[+] Building 31.7s (7/7) FINISHED                                                                                                                  
 => [internal] load build definition from Dockerfile                                                                                          0.4s
 => => transferring dockerfile: 124B                                                                                                          0.0s
 => [internal] load .dockerignore                                                                                                             0.5s
 => => transferring context: 2B                                                                                                               0.0s
 => [internal] load metadata for public.ecr.aws/lambda/python:3.8                                                                             3.5s
 => [1/2] FROM public.ecr.aws/lambda/python:3.8@sha256:313995d27e68d28fc879f28c24f3d13a185c083a1c41fef2d44afacfd03ff2dc                      25.5s
 => => resolve public.ecr.aws/lambda/python:3.8@sha256:313995d27e68d28fc879f28c24f3d13a185c083a1c41fef2d44afacfd03ff2dc                       0.0s
 => => sha256:313995d27e68d28fc879f28c24f3d13a185c083a1c41fef2d44afacfd03ff2dc 1.58kB / 1.58kB                                                0.0s
 => => sha256:eb3db1f34c3b76bc8614a677e26103ab66318b6a0b1af43064f47c33652881f5 2.89kB / 2.89kB                                                0.0s
 => => sha256:d519fd89485b556ac5741ddf554e274d7d2341df663202622ff0df17713b56ce 100.75MB / 100.75MB                                           16.0s
 => => sha256:c18accecece0cb85ff20fdb3dd2b221cc5d058e0cb3bae82e99218f26ac1d95f 417B / 417B                                                    1.0s
 => => sha256:6460572f426be4b5cfe45d592a01c053c74d1fce9478a8248f566217c3b5bd39 60.22kB / 60.22kB                                              2.0s
 => => sha256:03ac043af787c8cb06d6a7f8289c62cf97e630b08011717197ab2adb087d061d 3.31MB / 3.31MB                                                3.0s
 => => sha256:04f3d6691c40eabcab2a09fe0da44eb659d2d62fbf3f0770146c31d5ef39c339 54.41MB / 54.41MB                                             17.9s
 => => sha256:c5195ce15cfbc20ad941dec4a2f17da79f66a6bd054f99221c56c4b0551f858f 15.07MB / 15.07MB                                              7.8s
 => => extracting sha256:d519fd89485b556ac5741ddf554e274d7d2341df663202622ff0df17713b56ce                                                     1.5s
 => => extracting sha256:6460572f426be4b5cfe45d592a01c053c74d1fce9478a8248f566217c3b5bd39                                                     0.0s
 => => extracting sha256:c18accecece0cb85ff20fdb3dd2b221cc5d058e0cb3bae82e99218f26ac1d95f                                                     0.0s
 => => extracting sha256:03ac043af787c8cb06d6a7f8289c62cf97e630b08011717197ab2adb087d061d                                                     0.1s
 => => extracting sha256:04f3d6691c40eabcab2a09fe0da44eb659d2d62fbf3f0770146c31d5ef39c339                                                     1.6s
 => => extracting sha256:c5195ce15cfbc20ad941dec4a2f17da79f66a6bd054f99221c56c4b0551f858f                                                     0.8s
 => [internal] load build context                                                                                                             0.4s
 => => transferring context: 240B                                                                                                             0.0s
 => [2/2] COPY app.py ./                                                                                                                      0.8s
 => exporting to image                                                                                                                        0.8s
 => => exporting layers                                                                                                                       0.5s
 => => writing image sha256:a20f98e9a887e4ff6c7c82b84b821135bedd16ca6911f26d2f0dfbf6782a5ef3                                                  0.0s
 => => naming to docker.io/rie_python/latest                                                                                                  0.0s
```
### 起動

```
 $ docker run -p 9000:8080 rie_python/latest
```
port9000をコンテナの8080に紐づけて起動。


### curlから叩いてみる

```
 % curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{ "q":"Merry Christmas" }'                  
```
RIEで用意されているエントリポイントに向けて、jsonを投げてみると……

## あれ……うまくいっちゃった……
```

{"message": "recieved data is Merry Christmas"}% 
```
ちゃんと返ってきてしまいました……



## まとめ

ただRIEを試しただけの記事になってしまいました。もう少しなにかネタ用意しとけばよかった……反省。

とはいえ、簡単なものでしか試してないので、次回はx86版でゴリゴリ作ってあるイメージとか動かしてみたいと思います。