「NestJS」をAWS Lambda + API Gatewayで動かす

どうも!大阪オフィスの西村祐二です。

個人的にフロントエンドはAngularを使ってよく開発しています。

AngularはTypeScriptがデフォルトなので、APIのレスポンスを型定義するのですが、サーバーサイドもTypeScriptにして型定義を共有できたら良さそうだなと思っていました。

そこで最近、TypeScript製Node.jsフルスタックフレームワーク「NestJS」を調べています。

「NestJS」のイメージとしてはPythonの「Flask」やRubyの「Rails」を想像してもらえれば良いかと思います。

今回はその「NestJS」をAWS Lambda + API Gatewayのサーバーレス構成で動かしてみたいと思います。

環境

  • Node: 12.13.0
  • NestJS: 6.10.1
  • Serverless Framework: 1.57.0

作業概要

Angular同様にNestJSもCLIが提供されていますので、それを使ってプロジェクトを作成します。

LambdaへのデプロイはServerless Frameworkを使ってデプロイします。

node_modulesの容量が大きくなってしまうので、Lambda Layersを利用します。

Lambda Layersへのデプロイを簡単にするためにプラグインの「serverless-layers」を使用します。

試してみる

環境準備

パッケージをインストールします。

1
2
$ npm i -g @nestjs/cli
$ npm i -g serverless

NestJSのプロジェクト作成

NestJSのCLIを使ってプロジェクトを作成します。

今回は「serverless-nestjs」としています。

1
2
3
$ nest new serverless-nestjs
 
? Which package manager would you ❤️  to use? npm

プロジェクトが作成できたら、ローカルで実行しています。

1
2
$ cd serverless-nestjs
$ npm run start

ブラウザをひらき、「http://localhost:3000」にアクセスし

Hello World!

と表示されればOKです。

次はNestJSがLambdaで動くようにハンドラーファイルを作成します。

Lambda用のハンドラーファイルを作成

必要なライブラリをインストールします。

1
$ npm i aws-lambda aws-serverless-express express

API Gatewayからデータを受けとるためのLambdaハンドラーを作成します。

src/index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import { Context, Handler } from 'aws-lambda';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Server } from 'http';
import { ExpressAdapter } from '@nestjs/platform-express';
import * as serverless from 'aws-serverless-express';
import * as express from 'express';
 
let cachedServer: Server;
 
function bootstrapServer(): Promise<Server> {
  const expressApp = express();
  const adapter = new ExpressAdapter(expressApp);
  return NestFactory.create(AppModule, adapter)
    .then(app => app.enableCors())
    .then(app => app.init())
    .then(() => serverless.createServer(expressApp));
}
 
export const handler: Handler = (event: any, context: Context) => {
  if (!cachedServer) {
    bootstrapServer().then(server => {
      cachedServer = server;
      return serverless.proxy(server, event, context);
    });
  } else {
    return serverless.proxy(cachedServer, event, context);
  }
};

Serverless Frameworkの設定

プラグインをインストールします。

1
$ npm i -D serverless-layers

Layerをデプロイするために事前にS3にバケットを作成しておきます。

今回は「nestjs-lambda-layers」というバケットを作成しておきました。

NestJSはビルドコマンドでTypeScriptのファイルをJSに変換し、dist/に出力してくれるので、そのファイルをデプロイパッケージに含めデプロイします。

node_modulesのファイルはserverless-layersを使ってLayerとして紐付けます。

作成するAPI GatewayはAnyとして受け取ったリクエストはすべてLambdaで動くNestJSに渡すようにします。

serverless.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
service: serverless-nestjs
 
provider:
  name: aws
  runtime: nodejs10.x
  region: ap-northeast-1
 
plugins:
  - serverless-layers
custom:
  serverless-layers:
    layersDeploymentBucket: nestjs-lambda-layers
 
package:
  individually: true
  include:
    - dist/**
  exclude:
    - '**'
functions:
  index:
    handler: dist/index.handler
    events:
      - http:
          cors: true
          path: '/'
          method: any
      - http:
          cors: true
          path: '{proxy+}'
          method: any

これで準備完了です。

デプロイしてみる

下記コマンドを実行して、デプロイしてみましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
$ nest build && sls deploy
 
Serverless: [LayersPlugin]: Downloading package.json from bucket...
Serverless: [LayersPlugin]: package.json does not exists at bucket...
Serverless: [LayersPlugin]: Dependencies has changed! Re-installing...
npm WARN serverless-nestjs@0.0.1 No description
npm WARN serverless-nestjs@0.0.1 No repository field.
 
 
> @nestjs/core@6.10.1 postinstall /Users/yuji/study/nestjs/serverless-nestjs/.serverless/layers/nodejs/node_modules/@nestjs/core
> opencollective || exit 0
 
added 161 packages from 151 contributors and audited 885260 packages in 6.078s
found 0 vulnerabilities
 
 
Serverless: [LayersPlugin]: Created layer package /Users/yuji/study/nestjs/serverless-nestjs/.serverless/serverless-nestjs-dev.zip (13.6 MB)
Serverless: [LayersPlugin]: Uploading layer package...
Serverless: [LayersPlugin]: OK...
Serverless: [LayersPlugin]: New layer version published...
Serverless: [LayersPlugin]: Uploading remote package.json...
Serverless: [LayersPlugin]: OK...
Serverless: [LayersPlugin]: Associating layers...
Serverless: [LayersPlugin]: function.index - arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxxxxxxx:layer:serverless-nestjs-dev:2
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
........
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service index.zip file to S3 (42.58 KB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
.......................................
Serverless: Stack update finished...
Service Information
service: serverless-nestjs
stage: dev
region: ap-northeast-1
stack: serverless-nestjs-dev
resources: 14
api keys:
  None
endpoints:
  ANY - https://xxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/
  ANY - https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/{proxy+}
functions:
  index: serverless-nestjs-dev-index
layers:
  None
Serverless: [LayersPlugin]: function.index = layers.arn:aws:lambda:ap-northeast-1:xxxxxxxx:layer:serverless-nestjs-dev:2
Serverless: Run the "serverless" command to setup monitoring, troubleshooting and testing.

上記のようなログがでれば成功です!

これで、LambdaでNestJSが動く、API Gateway+Lambdaの構成ができました!簡単ですね。

デプロイしたAPIを叩いてみる

上記でAPI Gateway+Lambdaの構成ができたので実際に動かしてみたいと思います。

ログ出力のendpointsのところに出力されたURLにブラウザからアクセスしてみましょう。

するとローカル実行で確認したのと同じように「Hello World!」が出力されるかと思います!やりましたね!

さいごに

「NestJS」をAWS Lambda + API Gatewayの構成で動かしてみました。

「NestJS」はAngularのように開発できたり、CLIでローカル実行やビルド、テストなどが実行できたりと、いろんな機能が予め用意されているので、環境構築に手間がかからず、すぐに開発に取りかかれて良いです。

さらに、Serverless Frameworkを使えば、簡単に「NestJS」が動くAPI Gateway+Lambdaの構成を構築できます。

次はAngular+NestJSで実践的なものを作ってみたいと思います。

誰かの参考になれば幸いです。

PRもっと安く使いたい