2024-10-16
EC2 & ALB はコストが高すぎた。1 円にもならないこのブログのために 1 か月 $40 という大金が消えていた。そのうち移行しよう、なんて甘い考えだったが、マネジメントコンソールのコストを見ていたら居ても立っても居られなくなった。
なぜだかわからないがとても不安になった。
そこで急遽移行を始めた。
幸いバックエンドは複雑なコードではなく、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 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
ルートパス直下に
{proxy+}
リソースを作り、ANY メソッドで Lambda 関数を指定する。
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 だ。もっと早く移行すればよかった。悔やんでも仕方ない。