ABCABC Tech Catalog

Lambda Web AdapterでNext.jsアプリをお手軽にサーバレス化してみた

超簡単に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 --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.1 /lambda-adapter /opt/extensions/lambda-adapter

ENV NODE_ENV=production
ENV PORT=3000
ENV AWS_LWA_ENABLE_COMPRESSION=true

WORKDIR /app

COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /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以外の環境でもそのまま利用できるので、環境移行や別環境での検証が非常に容易で便利です!

非常に簡単で実用性も高いツールだと思うので、サーバレス構成を検討されている方に是非オススメしたいです。

AUTHOR

金谷 洋佑

朝日放送テレビ株式会社 技術局 技術開発部

動画・広告配信を主に取り組んでおり、その傍らでシステムのモダナイズの提案・支援や開発も担当。アプリケーションからネットワーク・セキュリティ・インフラまで幅広く励んでます!

WORK@ABC

技術力を培うための
環境と文化

ABCに昔から根付く「自分たちで開発する」文化を支える環境や取り組みをご紹介します
ABCについてもっと知る