AWS Lambda Web Adapterを使ってDeno + HonoをLambdaで動かす

2024/09/08に公開

はじめに

Hono の公式ドキュメントにはAWS Lambda での使用方法が書かれています。
ただ、Node.js や Bun でのデプロイ方法はありましたが、Deno での方法がありませんでした。
Deno + Hono を AWS Lambda で動かすことができないか?と調べてたところ、AWS Lambda Web Adapterを使えばいけそうだったので、試してみました。
結果、動作確認ができたので、その方法等を共有します。

AWS Lambda Web Adapter とは

Lambda Web Adapter『VM やコンテナ用で作られたウェブアプリを Lambda で動かすためのツール』 です。

https://aws.amazon.com/jp/builders-flash/202301/lambda-web-adapter/

Dockerfile に

COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter

を追加することで、Lambda のコンテナランタイムで Docker イメージを動かすことがでくるようになります。

AWS Lambda Web Adapter は何をしているのか

AWS Lambda Web Adapter は Lambda と統合先との間で以下のように動作しているようです。

  1. API Gateway 等から Lambda ランタイムがイベントを受信
  2. Web Adapter がイベントをパースし、HTTP リクエストに変換し、Web アプリのプロセスに HTTP に転送
  3. Web アプリがリクエストを処理し、HTTP でレスポンス
  4. Web Adapter が API Gateway 等が受け取る形式に変換し、Lmabda ランタイムへ返還
  5. Lambda ランタイムが API Gateway 等にレスポンスを返還

方法

私がプロジェクト作成からデプロイまでやったこととしては以下です。

  • VS Code DevContainer + Docker で Deno + Hono 開発環境を構築
  • Github Actions で Docker イメージのビルドと ECR へのプッシュ
  • AWS CDK で インフラ構築

本記事では作業の中でも特徴的だった

  • Dockerfile の記述
  • リッスンポート
  • AWS CDK でのインフラ構築

について記載します。

Dockerfile

FROM denoland/deno:1.46.2

COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter

WORKDIR /app

COPY deno.jsonc deno.lock main.ts routers.ts /app/

EXPOSE 8080

RUN deno cache ./main.ts

CMD ["deno", "task", "start"]

AWS Lambda Web Adapter を使うために、Dockerfile に

COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter

を定義しています。

また、依存関係を Docker イメージに詰めておかないと、Lambda 起動時に

failed caching npm package ...

というエラーが発生するので、依存関係も Docker イメージに詰めています。

RUN deno cache ./main.ts

リッスンポート

Lambda Web Adapter は8080ポートにトラフィックを送信します。

https://github.com/awslabs/aws-lambda-web-adapter?tab=readme-ov-file#configurations

ポートはAWS_LWA_PORTという環境変数で変更できます。

AWS CDK によるインフラ構築

AWS CDKは、AWS のインフラストラクチャをコードで管理するためのフレームワークです。

https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/home.html

本記事では専用の IAW ユーザや ECR リポジトリ、ECR への Docker イメージは作成&デプロイ済みであること前提とします。

AWS CDK でのインフラ構築は以下のようになります。
TypeScript で記述しています。

import { App, Duration, Stack, StackProps } from "aws-cdk-lib";
import lambda from "aws-cdk-lib/aws-lambda";
import ecr from "aws-cdk-lib/aws-ecr";
import iam from "aws-cdk-lib/aws-iam";
import { HttpLambdaIntegration } from "aws-cdk-lib/aws-apigatewayv2-integrations";
import apiGateway from "aws-cdk-lib/aws-apigatewayv2";

export class AppStack extends Stack {
  constructor(scope: App, id: string, props?: StackProps) {
    super(scope, id, props);

    const ecrRepoArn = ecr.Repository.fromRepositoryArn(
      this,
      "test-deno-hono",
      "arn:aws:ecr:ap-northeast-1:123456789000:repository/test-deno-hono"
    );

    const iamRole = new iam.Role(this, "TestDenoHonoRole", {
      assumedBy: new iam.ServicePrincipal("lambda.amazonaws.com"),
      managedPolicies: [
        iam.ManagedPolicy.fromAwsManagedPolicyName(
          "service-role/AWSLambdaBasicExecutionRole"
        ),
      ],
    });

    const testDenoHonoLambda = new lambda.DockerImageFunction(
      this,
      "TestDenoHono",
      {
        code: lambda.DockerImageCode.fromEcr(ecrRepoArn),
        memorySize: 512,
        timeout: Duration.seconds(180),
        role: iamRole,
      }
    );

    const integration = new HttpLambdaIntegration(
      "TestDenoHonoApiIntegration",
      testDenoHonoLambda
    );

    new apiGateway.HttpApi(this, "TestDenoHonoApi");
  }
}

new AppStack(new App(), "test-deno-hono-lambda-stack", {
  env: { region: "ap-northeast-1", account: "123456789000" },
});

実行は以下で実行できます。

deno run --allow-all npm:aws-cdk deploy --app 'deno run --allow-all ファイル名' -v

性能面について

レイテンシ、コールドスタート、メモリ使用量などの性能面については今回検証できていません。
以下の記事に性能面について Node.js + Express での比較が書かれているので、参考にしてください。

https://aws.amazon.com/jp/builders-flash/202301/lambda-web-adapter/

おわりに

AWS Lambda Web Adapter を使うことで、Deno + Hono を AWS Lambda で動かすことができました。
Deno も Hono もまだまだ新興な技術なので、今後、もっと良い Aws Lambda + Deno + Hono 環境ができることを期待します。

参考記事

https://aws.amazon.com/jp/builders-flash/202301/lambda-web-adapter/

https://github.com/awslabs/aws-lambda-web-adapter

https://qiita.com/rinfield/items/32ec3237d43000f19224

Discussion