HTTP server runs on AWS Lambda

(※この記事は 別媒体に投稿した記事 のバックアップです。 canonical も設定しています)



With aws-lambda-adapter, you can easily run an HTTP server on a container image on AWS Lambda.

# Dockerfile
+ COPY /lambda-adapter /opt/extensions/lambda-adapter


I read a Japanese article about how to convert a web app to serverless.

I‘m interested in Rust, I tried to run an HTTP server using Rust web framework on AWS Lambda.

Example repository

HTTP server example (Rust — axum)

I implemented a HTTP Server by Rust and axum. This code is mostly sample code from axum repository.

use axum::{
    routing::{get, post},
    Json, Router,
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;

async fn main() {
    // initialize tracing
    // build our application with a route
    let app = Router::new()
        // `GET /` goes to `root`
        .route("/", get(root))
        // `POST /users` goes to `create_user`
        .route("/users", post(create_user));
    // run our app with hyper
    // `axum::Server` is a re-export of `hyper::Server`
    let addr = SocketAddr::from(([0, 0, 0, 0], 8080));
    tracing::debug!("listening on {}", addr);

// basic handler that responds with a static string
async fn root() -> &'static str {
    "Hello, World!"

async fn create_user(
    // this argument tells axum to parse the request body
    // as JSON into a `CreateUser` type
    Json(payload): Json<CreateUser>,
) -> (StatusCode, Json<User>) {
    // insert your application logic here
    let user = User {
        id: 1337,
        username: payload.username,
    // this will be converted into a JSON response
    // with a status code of `201 Created`
    (StatusCode::CREATED, Json(user))

// the input to our `create_user` handler
struct CreateUser {
    username: String,

// the output to our `create_user` handler
struct User {
    id: u64,
    username: String,

Build container image

Prepare a Dockerfile

This Dockerfile is normal for a web application.

# Dockerfile
FROM rust:1-slim-buster as builder
COPY ./Cargo.toml /app/Cargo.toml
COPY ./Cargo.lock /app/Cargo.lock
COPY ./src /app/src

RUN cargo build --release
FROM debian:buster-slim
COPY --from=builder "/app/target/release/example-rust-server-on-lambda" "/app/example-rust-server-on-lambda"
ENTRYPOINT ["/app/example-rust-server-on-lambda"]

Add to copy “aws-lambda-adapter” step

Add a step to the Dockerfile to copy aws-lambda-adapter. Just added this step, and the container image will be able to run on AWS Lambda.

  FROM debian:buster-slim
+ COPY /lambda-adapter /opt/extensions/lambda-adapter
  WORKDIR /app
  COPY --from=builder "/app/target/release/example-rust-server-on-lambda" "/app/example-rust-server-on-lambda"
  EXPOSE 8080

Note: aws-lambda-adapter default port is “8080”. If your web application uses other port, you have to set environment variables.


Execute the following command to build the container image.

# Login to Amazon ECR Public
$ aws ecr-public get-login-password --region us-east-1 |
    docker login --username AWS --password-stdin

# Build container image
$ export DOCKER_TAG="IMAGE_NAME:latest"
$ docker build --tag "${DOCKER_TAG}" .

Push to Amazon ECR

Execute the following command to push to the your ECR repository.

$ export DOCKER_TAG="IMAGE_NAME:latest"

$ aws ecr get-login-password --region ap-northeast-1 |
    docker login --username AWS --password-stdin "${ECR_URI}"
$ docker tag "${DOCKER_TAG}" "${ECR_URI}"
$ docker push "${ECR_URI}"

Deploy to AWS Lambda with Pulumi

I deployed an axum HTTP server on AWS using Pulumi. The reason I used Pulumi is because I heard it is the modern IaC tool. However, you can deploy it any way you like, such as AWS console, Terraform, etc.

I wrote the following TypeScript code, but I’m a Pulumi beginner, so this code may not be the best way.

import * as aws from "@pulumi/aws";

const lambdaRole = new aws.iam.Role("example-rust-server-on-lambda-role", {
  assumeRolePolicy: {
    Version: "2012-10-17",
    Statement: [{
      Action: "sts:AssumeRole",
      Principal: {
        Service: "",
      Effect: "Allow",
      Sid: "",

new aws.iam.RolePolicyAttachment(
    role: lambdaRole,
    policyArn: aws.iam.ManagedPolicies.AWSLambdaExecute,

const lambdaFunction = new aws.lambda.Function(
    packageType: "Image",
    imageUri: process.env.ECR_URI,
    role: lambdaRole.arn,

new aws.lambda.FunctionUrl("example-rust-server-on-lambda", {
  authorizationType: "NONE",

Using Lambda function URLs

In this example, I use the Lambda function URLs. It provides an HTTP endpoint without using other services such as API Gateway.


Accessing HTTP endpoints via cURL and returns 200 Success.

# GET /
$ curl
Hello, World!

# POST /users
$ curl -XPOST \
    -H 'Content-Type: application/json' \
    -d '{"username":"mryhryki"}' \