Nxで作ったNestjsのアプリをServerless FrameworkでAWS Lambdaにデプロイする

この記事は、「AWS LambdaとServerless Advent Calendar 2020」4日目です。

Nxを使うことで、NestjsやReactなどのアプリケーションをモノレポで管理することができます。また、Serverless Frameworkを使うことで、NestjsやExpressなどのアプリケーションについてもより簡単にデプロイ・運用することができます。

ただし、この2つを組み合わせて使うにはすこし工夫が必要です。ということで今回はこの組み合わせ方について紹介します。

LambdaでNestjsを動かす準備とServerless FW系リソースを追加する

まずは必要なライブラリを追加しましょう。

$ yarn add serverless-lambda-nestjs

// For Serverless Framework
$ yarn add -D serverless-layers 

// For TypeScript
$ yarn add -D @types/aws-lambda

AWS Lambdaのハンドラーを main.tsに実装する

NxでNestjsのアプリケーションを作成した場合、エントリーポイントはsrc/main.tsで固定されます。これは設定ファイルを変更することで調整できますが、今回はそのまま使います。

AWS Lambdaで動かす場合も、nx serveでローカル実行する場合にも同じファイルを使うことになりますので、どちらでも動くように調整します。

import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { ServerlessNestjsApplicationFactory } from 'serverless-lambda-nestjs';
import { APIGatewayProxyHandler } from 'aws-lambda';
import { AppModule } from './app/app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const globalPrefix = 'api';
  app.setGlobalPrefix(globalPrefix);
  app.enableCors({
    origin: '*',
    allowedHeaders: 'Origin, X-Requested-With, Content-Type, Accept',
  });
  const port = process.env.PORT || 3333;
  await app.listen(port, () => {
    Logger.log('Listening at http://localhost:' + port + '/' + globalPrefix);
  });
}

// Run Nestjs application locally
if (process.env.NX_CLI_SET) {
  bootstrap();
}

// Run Nestjs application in AWS Lambda
export const handler: APIGatewayProxyHandler = async (event, context) => {
  const app = new ServerlessNestjsApplicationFactory<AppModule>(
    AppModule,
    {
        // NestFactory.create's option object
        cors: {
          origin: '*',
          allowedHeaders: 'Origin, X-Requested-With, Content-Type, Accept',
        },
    }
  );
  const result = await app.run(event, context);
  return result;
};

NX_CLI_SET はNx CLIを使った場合に付与される環境変数です。ということで、この環境変数が含まれる場合は一般的なNestjsアプリケーションとして起動します。また、handler関数をexportしてありますので、これを利用するAWS Lambdaの関数を用意すれば、Lambdaの中でもNestjsを動かすことができます。

serverless.yaml をプロジェクトルートに配置する

続いてServerless FrameworkのYAMLファイルを作成します。

NxがビルドするNestjsのアプリは、/<PROJECT_ROOT>/dist以下に配置されます。そのため、Nestjsのアプリがあるディレクトリではなく、ルートに配置します。

service: nx-nestjs-api

custom:
  prune:
    automatic: true
    number: 3
  serverless-layers:
    dependenciesPath: ./package.json

provider:
  name: aws
  runtime: nodejs12.x
  region: us-east-1
  profile: default
  stage: development
plugins:
  - serverless-layers

package:
  individually: true
  include:
    - dist/apps/api/**
  exclude:
    - '**'

functions:
  index:
    handler: dist/apps/api/main.handler
    events:
    - http:
        cors: true
        path: '/'
        method: any
    - http:
        cors: true
        path: '{proxy+}'
        method: any

Build and Deploy

あとはデプロイするだけです。distを指定していますので、かならずデプロイ前にビルドしましょう。

# Build Nestjs applciation
$ yarn build

# Deploy to AWS
$ serverless deploy

Comment