Home
Blog
Products
Profile
Study
Collatz
© 2024 Oizumi Yuta

ブログのサーバを EC2 から Lambda に移行した

2024-10-16

EC2 & ALB はコストが高すぎた。1 円にもならないこのブログのために 1 か月 $40 という大金が消えていた。そのうち移行しよう、なんて甘い考えだったが、マネジメントコンソールのコストを見ていたら居ても立っても居られなくなった。

なぜだかわからないがとても不安になった。

そこで急遽移行を始めた。

Lambda 関数の作成

幸いバックエンドは複雑なコードではなく、index.js という 1 つのファイルだけだった。ChatGPT にどのようにデプロイしたらよいか聞いた。

AWS Lambdaは、ファイルシステムへの長期的なアクセスや常駐プロセスの保持を前提としていないため、標準的なExpressサーバーのコードをそのままLambdaにデプロイすることはできません。ただし、AWS LambdaでExpressアプリケーションを実行するために、aws-serverless-expressなどのライブラリを使用してHTTPリクエストを処理する形に変換することが一般的です。

コードも書いてもらった。

import awsServerlessExpress from 'aws-serverless-express'; // 新規追加

// 他は現行コードのまま

// サーバーをAWS Lambdaに対応させる
const server = awsServerlessExpress.createServer(app);

export const handler = (event, context) => {
  return awsServerlessExpress.proxy(server, event, context);
};

最後の部分は以下のリッスンする処理を削除して書き換える。

const port = 8080;
app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

レイヤー作成手順

次にレイヤーを作成する。

mkdir lambda-layer # 適当な作業ディレクトリ
mkdir next-blog-app # このアプリの作業ディレクトリ
mkdir nodejs # レイヤー作成に必須のディレクトリ
vi package.json # GitHub で管理している package.json をコピペする
npm install
cd ..
zip -r next-blog-app.zip nodejs

この後、マネジメントコンソール画面で、Lambda > レイヤー > レイヤーの作成 の順に進み、 zip 化したファイルをアップロードする。

require を import に書き換える

レイヤーを作ってコードをデプロイしたらテストする。

require is not defined in ES module scope, you can use import instead

テストしたら上記エラーが出たのでパッケージの使用は import に書き換える。

レイヤー更新

次のエラーは以下:

Cannot find package 'aws-serverless-express' imported from /var/task/index.mjs

EC2 で動かしていたころのパッケージには

aws-serverless-express
は含まれていなかったので、レイヤーに追加する必要があった。レイヤーを作り直す。

npm install aws-serverless-express
cd ..
zip -r next-blog-app.zip nodejs

API Gateway で REST API を作成する

ルートパス直下に

{proxy+}
リソースを作り、ANY メソッドで Lambda 関数を指定する。

image

CORS 設定を有効化し、API をデプロイする。

まとめ

aws-serverless-express
を初めて使った。めんどくさい設定が必要かと思ったら意外と簡単だった。 今まで 1 つの API に 1 つの Lambda 関数を関連付けていたが、ANY メソッドと
{proxy+}
リソースと謎のコードによって 1 つにまとめることができることを知った。

const server = awsServerlessExpress.createServer(app);

export const handler = (event, context) => {
  return awsServerlessExpress.proxy(server, event, context);
};

移行後早速 EC2 インスタンスを停止し、ALB を削除した。今月既に $20 だ。もっと早く移行すればよかった。悔やんでも仕方ない。