LoginSignup
7

More than 3 years have passed since last update.

ServerlessFrameworkで作る初めてのサーバーレスアプリケーション

Posted at

初投稿になります。
都内不動産Web系企業にて新卒として入社して3ヶ月ほどが経過しました。

SalesForceやAWSなど、クラウド系のツールをよく使っています。

サーバーレスフレームワークを最近業務上ではない部分で個人的に勉強をしているので、投稿していきたいと思います。

ServerlessFrameworkとは

直訳気味に説明すると下記になります。

サーバーレスフレームワークとは、イベント駆動かつ、実行ごとに課金される仕組みで、オートスケーリングなfunctionをビルド、デプロイを支援してくれるCLIツールです。

簡単にいうなら、AWSなどのクラウドプロバイダを使ってより手軽にサーバーレスアプリケーションを作ることのできるツールになっています。本来ならGUIでポチポチと設定しなければいけないLambdaやAPI Gateway、DynamoDBなどの設定をコードで記入できるのも魅力になっています。

ServerlessFrameworkのインストール

install
npm install -g serverless

基本コマンド

basic
serverless create --template aws-nodejs --path productName
// サーバーレスアプリの作成
serverless deploy -v
// デプロイ
serverless deploy function -f hello
//functionを指定したデプロイ

上記を見ていただけばわかるように、とても簡単にサーバーレスなアプリケーションを作成、デプロイまでできてしまいます。

サンプルアプリの作成

それでは実際に作成に移っていきましょう。上記で紹介したコマンドでアプリケーションを作成します。

install
 sls create -t aws-nodejs -path sls-sample

では早速dynamoDBのテーブルの作成を行います。ymlファイルの記述を行います。
sls createで作成されたymlファイルの編集を行います。

serverless.yml
service: sls-sample

plugins:
  - serverless-offline

custom:
  allowedHeaders:
    - Accept
    - Content-Type
    - Content-Length
    - Authorization
    - X-Amz-Date
    - X-Api-Key
    - X-Amz-Security-Token
    - X-Amz-User-Agent
    - app_user_id
    - app_user_name

provider:
  name: aws
  runtime: nodejs10.x
  region: ap-northeast-1
  stage: prod
  memorySize: 128
  timeout: 5
  endpointType: regional
  environment:
   ARTICLES_TABLE: ${self:service}-${opt:stage, self:provider.stage}
  iamRoleStatements:
    - Effect: Allow
      Action: 
        - dynamodb:Query
        - dynamodb:PutItem
      Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.ARTICLES_TABLE}"

functions:
  add-article:
    handler: api/add-article.handler
    description: POST /article
    events:
      - http:
          path: article
          method: post
          cors:
            origin: '*'
            headers: ${self:custom.allowedHeaders}

resources:
  Resources:
    ArticlesTable:
      Type: AWS::DynamoDB::Table
      DeletionPolicy: Retain
      Properties:
        TableName: ${self:provider.environment.ARTICLES_TABLE}
        AttributeDefinitions:
          - AttributeName: user_id
            AttributeType: S
          - AttributeName: timestamp
            AttributeType: N
          - AttributeName: article_id
            AttributeType: S
        KeySchema:
          - AttributeName: user_id
            KeyType: HASH
          - AttributeName: timestamp
            KeyType: RANGE
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        GlobalSecondaryIndexes:
          - IndexName: article_id-index
            KeySchema:
              - AttributeName: article_id
                KeyType: HASH
            Projection:
              ProjectionType: ALL
            ProvisionedThroughput:
              ReadCapacityUnits: 1
              WriteCapacityUnits: 1

記述内容は上記のようになります。ymlファイルは複雑なように見えますが、一つ一つの単語の意味が明確なので、設定をコードでやっているだけで、実際のファイル作成とあまり難しさは変わりません。

それに、コードを見れば一発でどんな設定を行ったかがわかるので、かなり便利だと思います。

basic

serverless deploy -v

//functionを指定したデプロイ

それではデプロイをしてAWSにログインし、dynamoDBを見てみてください。
実際に新しいテーブルが作られているはずです。

POST機能

add-article.js
/**
 * Route: POST /article
 */

const AWS = require('aws-sdk');
AWS.config.update({ region: 'ap-northeast-1'});

const moment = require('moment');
const uuidv4 = require('uuid/v4');

const dynamodb = new AWS.DynamoDB.DocumentClient();
const tableName = process.env.ARTICLES_TABLE;

exports.handler = async (event) => {
    try {
        let item = JSON.parse(event.body).Item;
        item.user_id = event.headers.app_user_id;
        item.user_name = event.headers.app_user_name;
        item.article_id = item.user_id + ':' + uuidv4()
        item.timestamp = moment().unix();
        item.expires = moment().add(90, 'days').unix();

        let data = await dynamodb.put({
            TableName: tableName,
            Item: item
        }).promise();

        return {
            statusCode: 200,
            headers: {
                'Access-Control-Allow-Origin': '*'
            },
            body: JSON.stringify(item)
        };
    } catch (err) {
        console.log("Error", err);
        return {
            statusCode: err.statusCode ? err.statusCode : 500,
            headers:{
                'Access-Control-Allow-Origin': '*'
            },
            body: JSON.stringify({
                error: err.name ? err.name : "Exception",
                message: err.message ? err.message : "Unknown error"
            })
        };
    }
}

では実際にこのサーバーレスフレームワークをオフラインで用いることのできるツールである「serverless-offline」を用いてテストをしてみます。

npm i --save serverless-offline

このコマンドでlocalhost:3000でオフラインでアプリケーションが動くようになります。
Postmanなどを使ってPOSTリクエストを叩いてみてください! 
URLは下記になります。
localhost:3000/article

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7