以前挫折したこの組み合わせを、再度挑戦している。

ある程度知見としてまとまったら、Zennとかに書こうかと思うので、一旦今日の概要をメモ書きぐらいで残しとく。

ちなみに、参考資料はここらへん

devcontainerで環境構築

Dockerfileはこんな
ちなみにデフォルトのやつをちょろっといじっただけなので、絶対にこれより最適化されたものはあるはず

# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.224.3/containers/typescript-node/.devcontainer/base.Dockerfile

# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 16, 14, 12, 16-bullseye, 14-bullseye, 12-bullseye, 16-buster, 14-buster, 12-buster
ARG VARIANT="16-bullseye"
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT}

# [Optional] Uncomment this section to install additional OS packages.
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
    && apt-get -y install --no-install-recommends sqlite3

# [Optional] Uncomment if you want to install an additional version of node using nvm
# ARG EXTRA_NODE_VERSION=10
# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}"

# [Optional] Uncomment if you want to install more global node packages
# RUN su node -c "npm install -g "

nestjsでhello world

# nest cliをインストール
npm i @nestjs/cli

# プロジェクト作成
npx nest new .

# 実行
npm run start

これだけでlocalhostに立ち上がったAPIでhello worldは行けるはず。
メチャクチャ楽。

serverless frameworkを入れてデプロイまで

npm i -g serverless
npm i -S aws-lambda aws-serverless-express express
npm i -D serverless-layers serverless-offline

# AWSのクレデンシャル登録
serverless config credentials --provider aws --key dummyKey --secret dummySecretKey

こんな感じでAWSの情報をserverless frameworkに覚えさせる。

lambda用のハンドラ関数も以下のように準備

src/handler.ts

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;

async function bootstrapServer(): Promise<Server> {
  const expressApp = express();
  const adapter = new ExpressAdapter(expressApp);
  const app = await NestFactory.create(AppModule, adapter);
  app.enableCors();
  await app.init();
  return serverless.createServer(expressApp);
}

export const handler: Handler = async (event: any, context: Context) => {
  if (!cachedServer) {
    const server = await bootstrapServer();
    cachedServer = server;
  }
  return serverless.proxy(cachedServer, event, context, 'PROMISE').promise;
};

serverless.ymlも以下のように準備

service: serverless-sample
 
plugins:
 - serverless-layers
 - serverless-offline
 
provider:
 name: aws
 runtime: nodejs14.x
 region: ap-northeast-1
 memorySize: 256
 logRetentionInDays: 1
 apiGateway:
   minimumCompressionSize: 1024
 environment:
   AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1
   LANG: ja_JP.UTF-8
 versionFunctions: false
 deploymentBucket:
   name: sample-serverless-deploymentbucket
 
package:
 individually: true
 include:
   - dist/**
 exclude:
   - "**"
functions:
 index:
   handler: dist/handler.handler
   events:
     - http:
         cors: true
         path: "/"
         method: any
     - http:
         cors: true
         path: "{proxy+}"
         method: any

ちなみに、上記の状態でsample-serverless-deploymentbucketっていうS3を用意しておかないと、デプロイで「バケットがないよ!」って怒られます。

でもって、package.jsonに以下のスクリプトを追加

"scripts": {
  "deploy:dev": "nest build && serverless deploy",
  "deploy:prod": "nest build && serverless deploy --stage prod"
},

でもって、デプロイ

nest build && serverless deploy

デプロイ終わったら、urlが発行されてるので、それを叩くとHello worldできるはず

ローカル実行

さらっとnpm installの中に、serverless-offlineっていうプラグインも含めており、こいつを使うとローカルでLambdaの実行が可能

以下のファイルを追加

.vscode/launch.json

{
  "configurations": [
    {
      "name": "Lambda",
      "type": "node",
      "request": "launch",
      "runtimeArgs": ["--inspect", "--debug-port=9229"],
      "program": "${workspaceFolder}/node_modules/serverless/bin/serverless",
      "args": ["offline"],
      "port": 9229,
      "console": "integratedTerminal"
    }
  ]
 }

vscodeでデバッガを実行するとローカルでも動かせるようになるよ

次にやりたいこと

とりあえずデプロイとローカル環境構築まではいったので、dynamodbとのつなぎ込みをやりたい。