先日こんな記事を書きました!
Rustの「Axum」というWebAPI用のフレームワークを利用して、レイヤードアーキテクチャでTodoアプリを作る記事になります。
その過程でちょっとこだわってDockerfileを作成したので、せっかくなのでこれをAWSのLambdaを使ってサクッとデプロイしてみようと思います!
Lambda Web Adapterという比較的最近リリースされた機能を利用すると、Dockerイメージをほんの数分でデプロイできるので、今回はこちらを利用していきます!
Dockerfileを作成
僕の書いた記事でも紹介していますが、今回はこちらのリポジトリを使っていきます。
Dockerfileは以下のようになっています。
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のサーバーが立ち上がっていることを確認します。
% docker build -t axum-test .
% docker container run --rm -p 8080:8080 axum-test
http://localhost:8080 に接続すると200番のステータスが返ってくると思います!
ECRにプッシュ
AWSのマネジメントコンソールを利用して作業していきます。
以下のようにECRに適当な名称(今回はaxum-test)をつけてプライベートのリポジトリを作成しておきます。
右側に「プッシュコマンドを表示」のようなボタンがあるのでクリックすると、コマンドが4つほど表示されるので、ローカルのターミナルで順に実行していってください。
(事前にdockerやAWS CLIがインストールされ、AWS CLIの設定が済んでおりAWSに接続できる前提です。)
アカウント名は伏せていますが、だいたい以下のようなコマンドになると思います。
% 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にプッシュされたイメージを選択していきます。
ただし、アーキテクチャは「x86_64」を指定しましょう!
ビルド時にはplatformにarm64を指定しましたが、ここではx86_64を指定します。
ややこしいので、注意しましょう。
関数が作成されたら、「設定」→「関数URL」を作成しましょう。
今回はデモ用なので認証タイプは「NONE」に設定しAPIをパブリックに接続可能な状態にしておきましょう。
(本番運用する際はIAMで認証をかけるか、API内部で認証認可の設定などを行いましょう)
この手順のみで、APIが公開されました!!!!!
やばいですね!
接続確認
今回は https://bhcdeeod7pkauu45xj5uxhgriq0fwbzl.lambda-url.ap-northeast-1.on.aws/ というURLが発行されたので、リクエストを送ってみましょう!
(HTTPieというアプリを使いました。)
正常にリクエストが返ってきていることがわかりますね!
あとはCloudFrontに繋ぐなり煮るなり焼くなりなんでもOKです!
終わりに
ということでRustで作ったWebAPIをLambda Web Adapterで簡単にデプロイしちゃう方法を書きました。
開発効率がとんでもなく上がるので皆さん使ってみてください!