Rust (axum) で作った API をコンテナ Lambda としてデプロイする
皆さんはRustで作ったAPIをどのようにデプロイしていますか?
シングルバイナリとしてデプロイすることも考えられますが、今回はあえてDockerコンテナを使い、簡単にLambdaにデプロイできることを確かめていきます。
使用技術 : Lambda Web Adapter
今回の肝となるのはLambda Web Adapterです。
これは、Dockerコンテナ上に作られたHTTP APIであれば何でも、Dockerfileに1行追加するだけ
でLambdaにデプロイできるようになるという技術です(LaravelをLambdaにデプロイした例もあります)。
これを使うことで、Lambdaのhandler
を意識しなくて良くなるため、Lambda以外のサーバー(ECSなど)への可搬性も格段に上がります。
もちろん、ローカルでの開発形態も変える必要がないため、導入コストが非常に低いです。
環境構築
全体像はこちらのリポジトリで確認できます。
以下では主なファイルについて見ていきます。
Cargo.toml
こちらはaxumのドキュメントをもとに作成しています。
[package]
name = "axum-lambda-deploy-sample"
version = "0.1.0"
edition = "2021"
[dependencies]
axum = "0.7.5"
tokio = { version = "1.40.0", features = ["full"] }
tower = "0.5.1"
main.rs
こちらもaxumのサンプルをもとに作成しています。
一点異なるのは、ポートを8080
にしているところです。これはLambda Web Adapterがデフォルトでこのポートを要求するためです。
use axum::{routing::get, Router};
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(|| async { "Hello, World!" }));
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Dockerfile
ここではマルチステージビルドを活用してイメージを作成していきます。
FROM rust:1.81.0-bookworm as builder
WORKDIR /app
COPY Cargo.toml Cargo.lock /app/
RUN mkdir src
RUN echo "fn main() {}" > src/main.rs
RUN cargo build --release
RUN rm -r src
COPY src /app/src
RUN cargo build --release
FROM gcr.io/distroless/cc-debian12
COPY --from=builder /app/target/release/axum-lambda-deploy-sample /app/
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter
CMD ["/app/axum-lambda-deploy-sample"]
1つ目のイメージはRustの公式イメージで、こちらでリリースビルドを行います。
2つ目のイメージgcr.io/distroless/cc-debian12
は、Googleが提供している超軽量イメージdistrolessです。
最後から2行目に
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter
とありますが、ここでLambda Web Adapterを有効化しています。とても簡単ですね…!
Lambda にデプロイ
Docker イメージの準備
まずECRにaxum-lambda-deploy-sample
という名前のリポジトリを作成します。
そして、コンソール画面でプッシュコマンドを確認し、上から順に実行します(実行にはAWSの認証情報も必要です)。
なお、docker build
のときに以下のエラーが出ることがあります。
------
> FROM public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4:
------
failed to load cache key: unexpected status code [manifests 0.8.4]: 403 Forbidden
その場合は、
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws
を実行して再度やり直してください。
イメージがプッシュできていれば成功です。
Lambda 関数の作成
次にLambda関数を作成していきます。
コンテナイメージ
を選択し、関数名はaxum-lambda-deploy-sample
、コンテナイメージURIは上で作成したものを選択します。
ここでアーキテクチャ
はビルドしたマシンと同じものを選択してください。私はM1 Macなのでarm64としています。あるいはイメージビルド時に
docker build --platform linux/amd64 -t axum-lambda-deploy-sample .
とすると(ビルド時間はかなり伸びますが)x86_64でビルドできます。
関数を作成したら、次に関数URLを作成します。
以下の画面の関数URLを作成
を押し、次の画面で認証タイプはNONE
を選択し保存します。
API の実行
関数URL
が発行されたら、これをブラウザやcurl
で確認してみましょう。
うまくHello, World!
と表示されましたか?