Rust・AxumのDockerイメージをAWS Lambdaにサクッとデプロイする（Lambda Web Adapter）

先日こんな記事を書きました！

https://qiita.com/nokonoko_1203/items/57fbbdddbf7975a1d803

Rustの「Axum」というWebAPI用のフレームワークを利用して、レイヤードアーキテクチャでTodoアプリを作る記事になります。

その過程でちょっとこだわってDockerfileを作成したので、せっかくなのでこれをAWSのLambdaを使ってサクッとデプロイしてみようと思います！

Lambda Web Adapterという比較的最近リリースされた機能を利用すると、Dockerイメージをほんの数分でデプロイできるので、今回はこちらを利用していきます！

- 参考記事
    - [Lambda Web Adapter でウェブアプリを (ほぼ) そのままサーバーレス化する](https://aws.amazon.com/jp/builders-flash/202301/lambda-web-adapter/)

## Dockerfileを作成

僕の書いた記事でも紹介していますが、今回はこちらのリポジトリを使っていきます。

https://github.com/nokonoko1203/todos-layerd

Dockerfileは以下のようになっています。

```docker
FROM rust:1.74.1-slim-bullseye as base

FROM base as builder
WORKDIR /work
COPY . /work
RUN cargo build --release
RUN strip /work/target/release/todos-controller -o /todos-controller

FROM gcr.io/distroless/cc
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.7.1 /lambda-adapter /opt/extensions/lambda-adapter
COPY --from=builder /todos-controller /
EXPOSE 8080

CMD [ "/todos-controller" ]
```

`Lambda Web Adapter`を利用する上で肝になるのは、`COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.7.1 /lambda-adapter /opt/extensions/lambda-adapter`という行のみで、これをDockerfileに追加するだけで、LamdbaでWebAPIのコンテナがそのまま動くようになります。

やばいですね！

cloneしてもらって、トップレベルのディレクトリで以下のコードを実行し、ローカルホストでAxumのサーバーが立ち上がっていることを確認します。

```bash
% docker build -t axum-test .
% docker container run --rm -p 8080:8080 axum-test
```

http://localhost:8080 に接続すると200番のステータスが返ってくると思います！

## ECRにプッシュ

AWSのマネジメントコンソールを利用して作業していきます。

以下のようにECRに適当な名称（今回はaxum-test）をつけてプライベートのリポジトリを作成しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/041bd2e3-7084-a44c-230c-a58104371f67.png)

右側に「プッシュコマンドを表示」のようなボタンがあるのでクリックすると、コマンドが4つほど表示されるので、ローカルのターミナルで順に実行していってください。
（事前にdockerやAWS CLIがインストールされ、AWS CLIの設定が済んでおりAWSに接続できる前提です。）

アカウント名は伏せていますが、だいたい以下のようなコマンドになると思います。

```bash
% aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin <your_account_name>.dkr.ecr.ap-northeast-1.amazonaws.com
% docker build --platform=linux/amd64 -t axum-test .
% docker tag axum-test:latest <your_account_name>.dkr.ecr.ap-northeast-1.amazonaws.com/axum-test:latest
% docker push <your_account_name>.dkr.ecr.ap-northeast-1.amazonaws.com/axum-test:latest
```

2つ目のコマンドだけ要注意で、`docker build --platform=linux/amd64 -t axum-test .`としています。
僕のマシンがM1のMacOSなので、イメージ作成時に`--platform=linux/amd64`を指定する必要がありました。

amd64を指定してビルドしないとLambdaの側で`Error: fork/exec /opt/extensions/lambda-adapter: exec format error Extension.LaunchError`のようなエラーが発生し、デプロイされたURLに接続しても502のエラーレスポンスが返ってきてしまいます。

正常にプッシュされたら、次のステップに進みます。

## Lambdaにデプロイする

新規に関数を作成します。
名称は適当につけてもよく、ECRのリポジトリ名と一致している必要はありません。

「コンテナイメージ」を選択し、ECRにプッシュされたイメージを選択していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/f5327bfb-7c70-ef53-c312-f50ca35e08d9.png)

ただし、アーキテクチャは「x86_64」を指定しましょう！
ビルド時にはplatformにarm64を指定しましたが、ここではx86_64を指定します。
ややこしいので、注意しましょう。

関数が作成されたら、「設定」→「関数URL」を作成しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/f388d9f1-d8f0-a469-f7ac-4d5a4efabf45.png)

今回はデモ用なので認証タイプは「NONE」に設定しAPIをパブリックに接続可能な状態にしておきましょう。
（本番運用する際はIAMで認証をかけるか、API内部で認証認可の設定などを行いましょう）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/2b83810c-2684-9aaa-db13-43a31a3f5b0c.png)

この手順のみで、APIが公開されました！！！！！
やばいですね！

## 接続確認

今回は https://bhcdeeod7pkauu45xj5uxhgriq0fwbzl.lambda-url.ap-northeast-1.on.aws/ というURLが発行されたので、リクエストを送ってみましょう！
（HTTPieというアプリを使いました。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/3460bf2e-8136-0fc3-828a-479f62e102da.png)

正常にリクエストが返ってきていることがわかりますね！

あとはCloudFrontに繋ぐなり煮るなり焼くなりなんでもOKです！

## 終わりに

ということでRustで作ったWebAPIをLambda Web Adapterで簡単にデプロイしちゃう方法を書きました。

開発効率がとんでもなく上がるので皆さん使ってみてください！