1️⃣
lambda memo
lambda memo
src.lambda.ts
npm install @vendia/serverless-express aws-lambda
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import serverlessExpress from '@vendia/serverless-express';
import { Context, APIGatewayEvent } from 'aws-lambda';
import { INestApplication } from '@nestjs/common';
let cachedServer; // コールドスタート対策のキャッシュ
async function bootstrap(): Promise<INestApplication> {
const app = await NestFactory.create(AppModule);
// SwaggerセットアップやCORS設定などを行う
// 例: const config = new DocumentBuilder().setTitle('Swagger').build();
// 例: const document = SwaggerModule.createDocument(app, config);
// 例: SwaggerModule.setup('api-docs', app, document);
//
// listenはしない。Lambdaではinit()のみ。
await app.init();
return app;
}
export const handler = async (event: APIGatewayEvent, context: Context) => {
if (!cachedServer) {
const app = await bootstrap();
const expressApp = app.getHttpAdapter().getInstance();
cachedServer = serverlessExpress({ app: expressApp });
}
return cachedServer(event, context);
};
Dockerfile
FROM public.ecr.aws/lambda/nodejs:22
WORKDIR /var/task
COPY package*.json ./
RUN npm ci
COPY . .
Nestのビルド
RUN npm run build
CMD ["dist/lambda.handler"]
SAMテンプレート (template.yaml)
このテンプレートでは「Api イベント」を設定しているので、API Gatewayが自動的に作成され、ANY /{proxy+} で全パスを受け取りLambdaへ転送
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Deploy Nest.js on AWS Lambda (Container Image) with SAM
Globals:
Function:
Timeout: 15 # Lambdaのタイムアウト秒数を指定
Resources:
NestLambdaFunction:
Type: AWS::Serverless::Function
Metadata:
BuildMethod: docker
DockerContext: .
Dockerfile: Dockerfile
Properties:
PackageType: Image
ImageConfig:
Command:
- dist/lambda.handler
Events:
ApiEvent:
Type: Api
Properties:
Path: /{proxy+}
Method: ANY
ビルド、ECRへのプッシュ
-
sam build --use-container
- Build Failed
- Error: Building image for NestLambdaFunction requires Docker. is Docker running?
- WSL2 上に Docker Engine を直接インストールしている場合
- sudo service docker start や sudo systemctl start docker などで、Docker デーモンを起動する。
- docker ps などで正常に動いていることを確認
- Build Failed
-
sam deploy --guided
- AWS CLI の設定ファイル:
~/.aws/credentials
や~/.aws/config
に複数のプロファイルを定義している場合-
sam deploy --guided --profile <profileName>
初回はパラメータ(スタック名、リージョン、ECRリポジトリの自動作成など)を聞かれます。
デプロイ時に自動で「ビルドしたイメージをECRにプッシュ」→「CloudFormationスタックを作成」→「Lambda + API Gateway」がデプロイ、という流れになります。
-
- AWS CLI の設定ファイル:
- アカウント確認
aws sts get-caller-identity
aws sts get-caller-identity --profile stg
(オプション) --use-container を使わずにビルドしたい場合
もしどうしても Docker を使わずにビルドしたい場合は、SAM によるコンテナビルドを使わずに ローカルビルド した成果物をそのまま Lambda にデプロイする方法もあります。
- sam build で --use-container を外す (ただし、Node.js のバージョンなどがローカル環境と Lambda ランタイムで整合性が取れていないとビルド結果が動かない可能性がある)
- 自分でビルドしたディレクトリを sam deploy --template template.yaml --guided などでデプロイ
しかし、コンテナイメージ形式でデプロイするなら sam build --use-container が望ましく、やはり Docker が必要になります。
Swagger UI 内から API を叩く設定(CORS など)
CORS 設定
- Lambda (Nest.js) 側で app.enableCors() や適切な CORS 設定を行っているか確認してください。
- API Gateway 側でも、必要に応じて CORS を許可する設定が求められる場合がありますが、ANY /{proxy+} + Nest であれば、基本的には Nest 側の CORS 設定を有効にしておけば十分です。
Swagger の servers セクション
- Swagger UI から「Try it out」を押した際に、どのベースURLにリクエストを送るかが決まります。
- デフォルトでは相対パス or localhost:3000 などになっていると、デプロイ先の API を正しく叩けないかもしれません。
- その場合は、DocumentBuilder() の addServer() などで実際のデプロイ URL を指定するか、あるいは相対パスに調整してください。
- 例:
const config = new DocumentBuilder()
.setTitle('My API')
.addServer('/') // 相対パスで同じドメインにリクエスト
// or
// .addServer('https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com')
.build();
- 多くの場合は 相対パス指定 にしておくと、Swagger UI を開いている URL と同じドメイン配下にリクエストを送るため、追加の設定なく動きやすいです。
Discussion
AWS Lambdaに紐づけるロールを事前に管理者などに作成してもらった場合、SAMのデプロイ時に「既存ロールを使う」設定を行うことで、IAMロールの自動作成をスキップできます。以下のステップで進めるのが一般的です。
管理者権限がある人(あるいはIAMの操作が可能な担当者)が、Lambda用のロールを作成します。
• 作成するロールには、以下のようなポリシーが必要です(例):
• Lambdaの実行に必要なポリシー(AWSLambdaBasicExecutionRole など)
• 必要に応じて、追加のサービス(DynamoDBやS3など)へアクセスするためのポリシー
作成されたロールのARN(例: arn:aws:iam::123456789012:role/MyPreCreatedLambdaRole)を控えます。
template.yaml の Lambda関数定義部分にある Properties に、Role というプロパティを追加し、既存ロールのARNを設定します。
例: template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: My Serverless App
Resources:
MyLambdaFunction:
Type: AWS::Serverless::Function
Properties:
PackageType: Image
ImageUri: <YOUR_ECR_IMAGE_URI or SAM build method>
Role: arn:aws:iam::123456789012:role/MyPreCreatedLambdaRole # ここで既存ロールを指定
Events:
ApiEvent:
Type: Api
Properties:
Path: /{proxy+}
Method: ANY
テンプレートを修正したら、改めて sam build → sam deploy --guided を実行します。
• sam build (イメージビルドやパッケージング)
sam build --use-container
sam deploy --guided
デプロイが成功すると、CloudFormationスタックが作成/更新され、LambdaとAPI Gatewayが紐づきます。
sam deploy の出力か、CloudFormationコンソールの「Outputs」で、API GatewayのURLを確認できます。
まとめ
1. 管理者に事前にロールを作成してもらう
• 必要ポリシー(Lambda実行権限等)を付与したロール。ARNをメモする。
2. template.yaml に Role: <ARN> を設定
• こうすることで、SAMが自動でIAMを作成しなくなる。
3. 自分(デプロイ者)には iam:PassRole 権限が必要
• これがないと、CloudFormationが「このロールをLambdaに紐づける」操作でエラーになる。
4. sam build && sam deploy --guided
• 正常に完了すれば、既存ロールを使ったLambdaデプロイが成功する。
これでPowerUserAccessのみを持っていて「IAMロールの作成」ができない状況でも、既存ロールを指定してデプロイが可能になります。