前回までのあらすじ
TypeScript な Express を aws-serverless-express で Serverless 化して AWS Lambda にデプロイしました。
データベースを使えるように AWS の DynamoDB に接続できるようにしてみたメモ。
serverless.yml に DynamoDB の設定を追加する
serverless.yml
に DynamoDB の設定・IAM role の設定を追加しておけば、デプロイした際に自動的に AWS に DynamoDB のテーブルが作成され接続できるようになるようです。
DynamoDB の設定・IAM role の設定をそれぞれ別のファイルで作成して serverless.yml
で読み込ませるようにします。
serverless.yml に設定ファイルを読み込ませる設定を追加する
serverless.yml
provider: stage: ${opt:stage, 'dev'} environment: NODE_ENV: ${self:provider.stage} # process.env.DYNAMODB_TABLE でテーブル名を取得できるようにする DYNAMODB_TABLE: TABLE_NAME-${opt:stage, self:provider.stage} # IAM role の設定を読み込む iamRoleStatements: ${file(./config/iam.yml)} resources: # DynamoDB の設定を読み込み - ${file(./config/dynamodb.yml)}
DynamoDB の設定
./config/dynamodb.yml
Resources: MtDynamoDbTable: Type: 'AWS::DynamoDB::Table' DeletionPolicy: Retain Properties: AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - AttributeName: id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1 TableName: ${self:provider.environment.DYNAMODB_TABLE}
この設定の基づき DynamoDB が作成される。
データベースのテーブル名は読み込み元の serverless.yml にある environment.DYNAMODB_TABLE
から取得される。
IAM role の設定
./config/iam.yml
- Effect: Allow Action: - dynamodb:Query - dynamodb:Scan - dynamodb:GetItem - dynamodb:PutItem - dynamodb:UpdateItem - dynamodb:DeleteItem Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"
DynamoDB を操作できる IAM role を設定
webpack で DYNAMODB_TABLE
をExpress に渡す設定
webpack.EnvironmentPlugin
を使うことで serverless.yml
の provider.environment
の値を process.env にマージしてプログラムに渡すことが出来る
webpack.config.js
const webpack = require('webpack'); const slsw = require('serverless-webpack'); const enviroment = slsw.lib.serverless.service.provider.environment.NODE_ENV || 'dev'; module.exports = { entry: slsw.lib.entries, // … plugins: [ new webpack.EnvironmentPlugin( slsw.lib.serverless.service.provider.environment, ), ], // … }
cf. TypeScript な Express を aws-seveless-express で Serverless にして AWS Lambda にデプロイするまでの記録 - かもメモ
DynamoDB に接続するサンプルのエンドポイントを作成
$ npm install --save aws-sdk
/src/app.ts
import express from 'express'; import * as AWS from 'aws-sdk'; import { v4 as uuid } from 'uuid'; const dynamoDB = new AWS.DynamoDB.DocumentClient({ apiVersion: '2012-08-10' }); const TABLE_NAME = process.env.DYNAMODB_TABLE || 'LOCAL_TABLE_NAME'; const app = express(); const router = express.Router(); // ... router.get( '/scan', async (req: express.Request, res: express.Response): Promise<void> => { try { const items = await dynamoDB .scan({ TableName: TABLE_NAME, }) .promise(); res.send(items); } catch (error) { res.status(400).send(error); } }, ); router.get( '/test', async (req: express.Request, res: express.Response): Promise<void> => { try { const item = { id: uuid(), param: 'test', }; await dynamoDB .put({ TableName: TABLE_NAME, Item: item, }) .promise(); res.send(item); } catch (error) { res.status(400).send(error); } }, ); // …
AWS に deploy
$ sls deploy --stage prod -v
デプロイが完了したら AWS コンソールで DynamoDB のテーブルが作成されていることを確認。
API Gateway で表示された http://エンドポイントのURL/test
で DynamoDB へのデータ作成・ http://エンドポイントのURL/scan
で DynamoDB に作成されたデータが表示されていれば OK
Local 環境での DynamoDB との共存
local環境は Docker で作成していました。
--stage prod
の時は AWS の DynamoDB に接続して、--stage dev
の時は Docker 上の DynamoDB に接続するようにします。
Docker 上の DynamoDB に接続するには設定が必要なので process.env.NODE_DEV
が prod
で無ければ接続先を Docker 上の DynamoDB に向ける設定をすれば OK
/src/app.ts
import express from 'express'; import * as AWS from 'aws-sdk'; import { v4 as uuid } from 'uuid'; if (process.env.NODE_ENV !== 'prod') { const config = { endpoint: 'http://localhost:XXXX', // docker 上の DynamoDB のエンドポイントURL region: 'northeast-1', }; AWS.config.update(config); } const dynamoDB = new AWS.DynamoDB.DocumentClient({ apiVersion: '2012-08-10' });
これで local 動作させる時は Docker の DynamoDB を使用できるようになりました!
₍ ᐢ. ̫ .ᐢ ₎👌 ヤッタネ
やっとアプリを開発できる下準備が出来ました…
後は画像を使いたい場合に S3 にアップロードする方法とかが必要になってきそうですが、それは追々…
[参考]