カテゴリー
【AWS Lambda使い方ガイド】AWS CLIから簡単なランタイムNodejs v18対応のLambdaをデプロイする手順
※ 当ページには【広告/PR】を含む場合があります。
2023/06/15

現在、AWS LambdaのNodejsのランタイムで推奨されるバージョンは
さらに、昨年の2022年11月には
v18でこれまでと大きく違うことは、デフォルトのハンドラーコードが
実際にLambdaのハンドラを生成してみると分かりますが、これまでの
index.js
index.mjs
ということで、typescriptの開発者としても嬉しい、
esbuild
ここではAWS Lambdaを利用する基礎中の基礎であるAWS CLIを使った簡単な使い方を、
esbuild
前置き
ここでは
AWS CLI
もし
AWS CLI
Lambda実行ロールの準備
Lambdaを新規作成する場合、必要最低限のIAMロールが一つ必要です。
通常はIAMダッシュボードから作成するか、管理者にロールの付与を依頼しましょう。
以下は適当に作った
lambda_basic_execution

AWS CLIからのLambdaのデプロイにはロールのARN値の設定が必要になります。
ちなみにARNの確認にもCLIコマンドを使うのが便利です。
$ aws iam list-roles | grep Arn
#...ARNのリストが表示される
"Arn": "arn:aws:iam::************:role/<Lambdaに割り当てる実行権限ロール>",
#...
#もしくはjqコマンドが使える場合
$ aws iam list-roles | jq '.Roles[].Arn'
#...ARNのリストが表示される
"arn:aws:iam::************:role/<Lambdaに割り当てる実行権限ロール>"
#...
Lambdaのプロジェクト作成 〜 esbuildでハンドラのビルドする
ここからは簡単なnodejsプロジェクトを作成し、
esbuild
nodejsプロジェクトのリソースを作成
適当なフォルダに移動し、必要最低限のリソースファイルを新規作成していきます。
$ touch package.json index.ts
とりあえず
package.json
{
"name": "my-lambda",
"version": "0.0.1",
"description": "To execise to use AWS lambda with nodejs18."
}
package.jsonを生成するだけなら、
$ yarn init
でもOKです。
また今回はtypescriptでソースコードを作成するので、以下のようにインストールを済ませておきましょう。
$ yarn add typescript @types/node tslib -D
typescriptの初期化(tsconfig.json)を行います。
$ yarn tsc --init
これで
tsconfig.json
ひとまずtypescriptの準備はこれでOKです。
トランスパイラをtscからesbuildに乗り換え
tscでもESMターゲットの出力も可能ではありますが、最近ではよりビルド・バンドルの高速化が出来る・
インストールも簡単で、
$ yarn add esbuild -D
$ touch esbuild.config.js
で利用可能になります。
また通常、
esbuild
esbuild.config.js
import esbuild from 'esbuild';
esbuild.build({
entryPoints: [
'./iindex.ts',
],
outdir: 'build',
outExtension: { '.js': '.mjs' },
bundle: true,
minify: true,
platform: 'node',
sourcemap: false,
target: ['node18'],
plugins: [],
external: [],
}).catch(() => process.exit(1));
で、
package.json
{
"name": "my-lambda",
"version": "0.0.1",
"description": "To execise to use AWS lambda with nodejs18.",
"scripts": {
"build": "rm -rf build && node esbuild.config.js"
},
"type": "module",
"devDependencies": {
"tslib": "^2.4.1",
"@types/node": "^20.0.0",
"esbuild": "^0.18.2",
"typescript": "^4.9.4"
}
}
今回は
esbuild
tsc
"type": "module",
esbuild:external指定でnodeパッケージ依存性を制御する
ここでは出番がありませんが、esbuildを使ってAWS Lambdaハンドラを作成する際には、
esbuild:external指定
ローカルの開発環境でインストールしているnodeでは動いても、AWS Lambdaのランタイムとして動作してるnodeでは正常に実行されないものがあり、esbuildでのビルド後のESMコード(mjs)から動作しないモジュールの依存性を取り除く必要があります。
例えばシェルコマンドがnodejs側から呼び出すことのできる
「shelljs」
「pm2」
こういった通常のAWS Lambdaでは動かないタイプのモジュールは
external
//...中略
esbuild.build({
//...
external: [
'shelljs',
'pm2'
],
}).catch(() => process.exit(1));
なお、除外したパッケージは、起動先のnodejs環境に別途グローバルインストールやローカルインストールする必要があることもお忘れなく。
esbuildでindex.tsをビルドする
まだ
index.ts
export const handler = async (event: any, context: any) => {
const response: any = { statusCode: 200, body: '' };
try {
response.body = {message: 'HELLO, NODEJS V18!!!'};
return response;
} catch (error) {
response.statusCode = 500;
response.body = `ERROR: ${error}`;
return response;
}
}
これまでのLambdaハンドラの作法とは少し違って
export const handler...
では早速、esbuildをトライしてみます。
$ yarn build
$ ls -la build/
-rw-r--r-- 1 node node 655 Jun 14 07:45 index.mjs
ビルド後は非常にコンパクトな
index.mjs
AWS CLIでLambdaをデプロイしてみる
今回のようにアップロードするリソースが小さいサイズで収まる場合には特に必要ないのですが、10MB超えてきたあたりから、ファイルを個別アップロードするのが転送速度的にも厳しくなってきます。
ということで、ここでは
index.mjs
ビルドしたソースを圧縮
適当に
tmp
zipコマンドで
build
tmp
$ mkdir tmp
$ zip -rj tmp/my-function.zip build/*
zip圧縮で-j(junk)オプションがないと困った話
個人的に少しハマったのですが、当初は何も考えずに、とりあえず
-rオプション
$ zip -r tmp/my-function.zip build/*
としていました。
-rオプション
build
$ zipinfo -1 my-function.zip
build/index.mjs
実はこの状態でLambdaにデプロイしてしまうと、Lambdaが
build
index.mjs
このまま
CloudWatch
2023-06-14T11:14:24.790Z undefined ERROR Uncaught Exception
{
"errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module 'index'\nRequire stack:\n- /var/runtime/index.mjs",
"stack": [
"Runtime.ImportModuleError: Error: Cannot find module 'index'",
"Require stack:",
"- /var/runtime/index.mjs",
" at _loadUserApp (file:///var/runtime/index.mjs:997:17)",
" at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1032:21)",
" at async start (file:///var/runtime/index.mjs:1195:23)",
" at async file:///var/runtime/index.mjs:1201:1"
]
}
というように、
index.mjs
「Cannot find module 'index'」
ということで、
build
-j(junk)オプション
build
$ zip -rj tmp/my-function.zip build/*
確認すると、
$ zipinfo -1 my-function.zip
index.mjs
となり、
build
すべてのリソースを一つにバンドルしてくれる
esbuild
ただし、Lambdaをzipしてアップロードするのに
node_modules
ともかく、zipでリソースを固めてデプロイする際には、圧縮ファイル内のフォルダ構造にも気を遣う必要があります。
AWS CLIからLambdaへデプロイ
以上で、デプロイの準備が整いましたので、いよいよAWS CLIを使ってリモートへデプロイしてみましょう。
初回のデプロイには、以下のコマンドを利用します。
$ aws lambda create-function \
--function-name [Lambdaの関数名] \
--runtime nodejs18.x \
--zip-file fileb://tmp/my-function.zip \
--role [Lambdaに割り当てる実行権限ロールのARN] \
--handler index.handler
問題なくデプロイされていれば、Lambdaのリストで表示されていると思います。
$ aws lambda list-functions | grep FunctionName
#...
"FunctionName": "Lambdaの関数名",
#...
さらにデプロイしたLambdaがちゃんと動作するか
invoke
$ aws lambda invoke \
--function-name [Lambdaの関数名] \
--payload '{"key1":"value1","key2":"value2","key3": "value3"}' \
response.json
#👇レスポンス
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
コード・
200
また実行後に正常にLambadからレスポンスが返れば、
response.json
ちなみにここでは
--payload
デプロイしたLambdaを更新する場合
最初のデプロイには
create-function
update-function-code
例えばソースコードを書き換えて、ビルドした後で、
$ aws lambda update-function-code \
--function-name [Lambdaの関数名] \
--zip-file fileb://tmp/my-function.zip
とすることで、Lambdaが更新されます。
デプロイしたLambdaを抹消する
なお要らなくなったLambdaは以下のコマンドで一発削除することができます。
$ aws lambda delete-function \
--function-name [Lambdaの関数名]
要らなくなったLamdbaが名前を指定するだけで抹消できるので、後片付けにはとても便利です。
まとめ
以上、ここではESMベースのソースコードと、最新のLambdaランタイム・Nodejs v18を念頭に、AWS CLIからデプロイするまでの一連の過程を説明してみました。
デプロイしたLambdaの動作確認はあくまで
lambda invoke
この
この関数URLの詳しい説明とAWS CLIからの設定方法について、
参考サイト
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー