WSL2からAWS LambdaにDocker containerをデプロイしてAPIとして動かすまで

# はじめに
現在開発中の機械学習を用いた簡単なサービスを作るにあたって、メインPCで処理させるのがどうしてもいやだったのでAWS Lambdaを使用しました。
現在のLambdaはDockerのimageサイズがが10Gまで対応してるので結構なんでも動かせます。
割り当てるメモリサイズを増やせばそこそこ性能も出るため、普通のモデルならGPUもいらないです。

今回は自身の忘備録もかねてwsl2からDocker containerをデプロイしてテストするまでを紹介します。
あまり細かい解説はしていないため、内容は手順書に近いです。

# 想定する読者
+ 細かいところはどうでもいいのでLambdaでとりあえず何か動かしたい人
+ AWSよくわかってない人(僕もよくわかってないです、間違ってるところあったら教えてください)

# なぜWSL2でやるのか
+ 僕がネイティブに色々入れるのが嫌いだから
+ 環境が統一されていることが多そう(＝誰でもそのまま動かせる)

# 実行環境
os:windows11 pro
wsl2:Ubuntu 18.04 LTS

# 本編

### 準備
まずはWSL2を導入してない人はこちらから導入しましょう。
[Windows10 WSL2にUbuntuをインストールする](https://rightxlight.co.jp/achievements/windows10-wsl2%E3%81%ABubuntu%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B/)

次にDockerをWSL2に導入しましょう。
僕はネイティブに何か入れるのが基本的に嫌なので、Docker on Desktopを入れないでよい方法を紹介したこの記事を参考にしました。(ubuntuの手順をそのまま踏むだけではありますが)
[Docker Desktopに依存しない、WindowsでのDocker環境](https://qiita.com/ohtsuka1317/items/617a865b8a9d4fb67989)

それと持ってない人はAWSのアカウントも作ってください。
[AWS](https://aws.amazon.com/jp/)

### 各種必要なパッケージのインストール

##### AWS CLIの導入
まずはAWS　CLIを導入します。

unzipがない場合はこちらを実行してください。

```none:wsl
sudo apt install unzip
```

次にCLIをダウンロードしてインストールしましょう。

```none:wsl
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
```

初期設定をします。
IAMユーザという権限周りを設定したユーザを作る必要があるため、以下の記事から「.csvのダウンロード」まで実施してください。
[UbuntuでAWS CLIを使えるようにする](https://qiita.com/SSMU3/items/ce6e291a653f76ddcf79)

wsl2上でsudoをつけてconfig設定をするとうまく設定を参照できないのかコケてしまったため、configは以下のように設定してください。

```none:wsl
aws configure
```

キーはcsvに書いてあるもの、リージョンは東京ならば`ap-northeast-1`を設定しましょう。

一応csvをimportしてユーザを登録できるのですが、最初のカラムが`user name`となっているところを`User name`と変える必要があります。(なぜなのか・・・)
[AWS CLI v2のconfigure Importを使ってみた](https://dev.classmethod.jp/articles/user-aws-cli-v2-configure-import/)

##### npm/nodejsの導入
色々試したのですが、wsl2では以下の方法がうまくいきました。

```none:wsl
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
source ~/.bashrc
nvm install stable --latest-npm
```

##### AWS CDKの導入
```none:wsl
npm install -g aws-cdk
```
`cdk`を入力して導入されているか確認してみてください。

### Lambdaへデプロイ

##### Lambdaデプロイ準備
あまりやることないですが、仮想環境にpythonライブラリを入れるのが通例っぽいのでそれの準備をしましょう。

```none:wsl
sudo apt-get install -y python3-venv
```

##### デプロイまで
以下の記事のサンプルが分かりやすいので、これに沿って進めていって下さい。
[画像をAPI Gateway+Lambdaで受け取って Pillow で処理する（AWS CDK）](https://qiita.com/ou-mori/items/f0045028b64e0263c3dd)

この記事の「デプロイ」の手前まで進んだらライブラリをインストールしましょう。
プロジェクトフォルダの`requirements.txt`を以下のように書き換えてください。

```none:requirements.txt
-e .
aws_cdk.aws_lambda
aws_cdk.aws_apigateway
```

書き換えたら仮想環境にライブラリをインストールします。
プロジェクトフォルダのルートで以下を実行してください。

```none:wsl
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

ここまで終わればデプロイができます。
プロジェクトフォルダのルートで以下のコマンドを実行しましょう。

```none:wsl
cdk deploy
```

### テスト
実際に動かしてみましょう。
ここでは一旦上で紹介した記事の通りにPGを作ったと仮定しています。

まずAWSのコンソールから実際に設定されたAPIのエンドポイントを見に行きます。
Lambdaのページに飛ぶとプロジェクトフォルダと同じ名前がついた関数があると思うのでクリックしてください。
次に以下のような画面が表示されるのでAPI GateWayをクリックしてください。

![スクリーンショット 2021-10-18 205646.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227719/f2709534-3119-5cd5-aaf3-c315aa1ab2e7.png)

そうするとAPIエンドポイントと書かれたURLが2つくらい表示されていると思うので、`~/prod`となっている方をコピーして以下のPGに貼り付けてください。
`~/test-invoke-stage`となっているものしかない時があったのですが、prodに書き換えたら普通に動きました。
ステージの更新にラグがあるのでしょうか？よくわかりません。

```python:api_test.py
import requests
import base64

with open("./sample.png", 'br') as f:
    encoded_img = base64.b64encode(f.read())

api_endpoint = [API-Endpoint]

r_post = requests.post(api_endpoint, data=encoded_img)
print(r_post.json())
```

pythonで上記のPGを実行して最終的に`{'status': 'ok'}`と表示されればうまくいっています。
※サンプルではpngが想定されているので気を付けてください

上手くいってない場合はログをチェックしましょう。
AWSコンソール→CloudWatch→ロググループ
と遷移し、それっぽいものを開くと以下のような画像が出てくると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227719/ceea90d0-2b78-f9e4-b91e-6af56919b4a2.png)

日時が近いものを開いてログを見るとどこでエラー出てるとかわかります。
また、標準出力もここに表示されるので色々書き出すとわかりやすそうです。

# その他情報
・機械学習モデルをデプロイしたい人
上で紹介した方と同じですが、以下の記事が分かりやすいです。
[PyTorch on Lambda で MNIST の推論を実行する API を作成する（AWS CDK）](https://qiita.com/ou-mori/items/cc2ec3254025faec1bc9)
僕の場合モデルは開発環境でCPUに移してからモデルごと保存するとそのままロードして使えました。

・Docker上でopencv使いたい人
以下をDockerfileに追加してください。(もちろんpipでも入れてください)

```Dockerfile
RUN yum update -y && \
   yum install -y mesa-libGL
```

・ローカルでテストしたい人
公式のページが分かりやすいです。
[Lambda コンテナイメージをローカルでテストする](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images-test.html)