超簡単にAWS LambdaでWebアプリを実行
AWS Lambdaを初めとするサーバレスのサービスは構築・管理の手軽さや従量課金制のコストメリットの点からよくよく重宝しております。
ただ実行方法が特有のものになっており、例えばLambdaですと、基本的に以下のような専用のインターフェースの関数を実行する形になります。
export const handler = async (event) => { // TODO implement const response = { statusCode: 200, body: JSON.stringify('Hello from Lambda!'), }; return response; };
そのため別環境のアプリをそのまま持ってきても正しく動作せず、わざわざインターフェースをLambda用に修正したり、serverless-expressなどのライブラリをフレームワークに応じて追加する必要があり、悩ましいポイントでした…
Lambda Web Adapterとは
Lambda拡張機能のオープンソースソフトウェアツールです。リポジトリはこちらになります。
Lambda Web Adapter は受け取ったLambdaイベントからHTTPリクエストを作り、Webアプリに渡してくれます。そしてWebアプリが返すHTTPレスポンスをLambdaの形式に変換してくれます。
これにより、Webアプリ側は特にLambdaを意識する事なく、そのままでLambda実行環境でも動作するようになります!
実装方法
今回はNext.jsを使用したWebアプリをLambdaにデプロイします。
Next.js側
next.config.tsにてstandalone buildの設定を行い、最小限の内容でビルドできるようにします。
import type { NextConfig } from "next"; const nextConfig: NextConfig = { output: "standalone", //追加 ... }; export default nextConfig;
これでパッケージサイズが小さくなり、Lambda側のクォータ制限にも引っかかりにくくなります。
run.shを作成し、コンテナ実行時にキャッシュディレクトリの作成とサーバ起動ができるようにしておきます。
#!/bin/bash -x [ ! -d '/tmp/cache' ] && mkdir -p /tmp/cache exec node server.js
Dockerfile作成
Lambda Web Adaptorバイナリをコンテナ内の/opt/extensionsにコピーする処理を、Dockerfileに1行を追加するだけです。
FROM public.ecr.aws/docker/library/node:22.11.0-slim # Lambda Web Adapterインストール COPY /lambda-adapter /opt/extensions/lambda-adapter ENV NODE_ENV=production ENV PORT=3000 ENV AWS_LWA_ENABLE_COMPRESSION=true WORKDIR /app COPY /app/public ./public COPY /app/package.json ./package.json COPY /app/.next/standalone ./ COPY /app/.next/static ./.next/static COPY /app/run.sh ./run.sh CMD exec ./run.sh
このように、導入方法が非常に簡単なのも嬉しいポイントです!
今回はDockerコンテナの形ですが、Zipパッケージ(非コンテナ)の場合でも同様に利用可能です。
あとは、通常のLambda実装の場合と同様に、コンテナイメージをビルド&デプロイしてあげればOKです!
個人的にハマった点
デプロイしてコンソールからLambda関数を実行した所、以下のエラーが発生しました。
{ "errorType": "Extension.LaunchError", "errorMessage": "RequestId: ce1ef2aa-4d89-48d4-a618-6d7f4537901c Error: fork/exec /opt/extensions/lambda-adapter: exec format error" }
どうやら今回は、Apple SiliconのMac上でビルドしたためarm64アーキテクチャ用のバイナリが生成されてしまっていたようです…
Dockerビルド時にアーキテクチャの指定を追加してあげると無事解決しました!
docker build --platform linux/amd64 -t <image_name>:<image_tag>
まとめ
たった1行をDockerfileに追加するだけで、LambdaにWebアプリを載せる事ができました。コンテナイメージはLambda以外の環境でもそのまま利用できるので、環境移行や別環境での検証が非常に容易で便利です!
非常に簡単で実用性も高いツールだと思うので、サーバレス構成を検討されている方に是非オススメしたいです。