BunをLambdaのカスタムランタイムで動作させてみた

2023.09.14

はじめに

JavaScript のランタイム、Bun 1.0 が 2023/9/8 にリリースされました。

Bun & Lambda カスタムランタイム利用の最初の一歩として、Lambda 上で Bun カスタムランタイムを動作させてみた記事になります。

事前準備: Bun のインストール

https://bun.sh/

こちらを見ながらインストールしました。

curl -fsSL https://bun.sh/install | bash

カスタムランタイム用の Layer をアップロードする

公式でカスタムランタイム用の Layer が用意されているので、こちらをクローンして利用していきます。

README に手順が記載されており、ほとんど手順通りで大丈夫です。

cd bun/packages/bun-lambda
bun install
bun run publish-layer

実行後、 マネジメントコンソール側に bun のLayerがあることを確認できればOKです。

ハマりポイント

  • oclif 関連で Warning が出たら package.json に以下を追加してみる
      "devDependencies": {
        ...
        "@oclif/plugin-plugins": "^3.5.0"
      }

  • AWS CLI で使用する profile を指定したい場合、以下のように publish-layer.ts の cli コマンドを組み立てているコード内に profile を記載する。

      const result = this.#aws([
        "lambda",
        "publish-layer-version",
        "--layer-name", layerName,
        "--region", regionName,
        "--description", '"Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager."',
        "--license-info", "MIT",
        "--compatible-architectures", arch === "x64" ? "x86_64" : "arm64",
        "--compatible-runtimes", "provided.al2", "provided",
        "--zip-file", `fileb://${output}`,
        "--output", "json",
        "--profile", "study-env", // ⭐️ここ
      ]);

Lambda 関数を作成&実行する

続きの手順を進めていきます。

完成系は以下のリポジトリに上げています。

handler の実装

今回は API Gateway から実行される Lambda を想定して実装しています。

Bun 特有の Util が使えるか試したいので、 Bun.inspect(obj) も記載。

export default {
  async fetch(request: Request): Promise<Response> {
    console.log(request.headers.get("x-amzn-function-arn"));

    // BunのUtilを使ってみる
    const obj = { foo: "bar" };
    console.log(Bun.inspect(obj));

    return new Response("Hello from Lambda!", {
      status: 200,
      headers: {
        "Content-Type": "text/plain",
      },
    });
  },
};

bun build とファイルの zip 化

bun build src/handler.ts --outfile ./dist/handler.js

cd dist
zip handler.js --output handler.js.zip

handler.js.zipのファイルが出来ていれば OK です。

Lambda 関数の作成

AWS マネジメントコンソールにて、Lambda 関数を作成していきます。

ランタイム: Amazon Linux2

アーキテクチャ: arm64

Lambda関数を作成している

Layer の設定

先ほど作成したレイヤーを Lambda に設定。

Bunのカスタムランタイムレイヤーを追加している画像

ハンドラの設定

ここが少しハマりポイントでした。

ランタイム設定のハンドラの設定を handler.fetch に変更します。

追加したLayerをLambdaにアタッチ

Lambda ソースのアップロード

先ほど作成した handler.js.zip を選択しアップロードします。

zipファイルをLambdaにデプロイ

テスト

API Gateway からの呼び出しを想定したソースになっているので、テストのテンプレートで apigateway-aws-proxy を選択し、テスト実行します。

実行結果:

START RequestId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx Version: $LATEST
INFO RequestId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx "arn:aws:lambda:ap-northeast-1:123456789012:function:bunApiFunction"
INFO RequestId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx "{\n  foo: \"bar\"\n}"
END RequestId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx
REPORT RequestId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx	Duration: 169.34 ms	Billed Duration: 1159 ms	Memory Size: 128 MB	Max Memory Used: 87 MB	Init Duration: 988.86 ms

ちゃんと console.log(Bun.inspect(obj)); の結果も出力されていることが確認できました!

感想

カスタムランタイムをプロダクト環境で運用することは、ほぼ無いと思いますが触ってみて作り方が分かったので良かったです。

実行速度が速いのは魅力的なので、引き続きBunを追っていきたいです。