0
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

RDSとServerlessFrameworkでおみくじを作ろう

はじめに

AWSの使っておみくじアプリを作るよ(そんなのRDSを使わなくてもよくね?という話はナシで)

環境

node.js v12.18.3

作ってみる

DBインスタンスの作成

ここを参考にRDSを使ってDBインスタンスを作成していく

DBの設定

- データベース作成方法:簡単作成
- 設定:MySQL
- インスタンスサイズ:無料利用枠
- DBインスタンス識別子:aws-web-service
- マスターユーザー名:admin
- マスターパスワード:各自おまかせ
- パブリックアクセス可能:あり

作成したDBインスタンスのエンドポイントとマスターユーザーを使ってDBインスタンスにアクセス。

console
mysql -h mysql-80.xxx.{リージョン}.rds.amazonaws.com -P 3306 -u admin -p

RDSをパブリックアクセス可能にしてるのでセキュリティ的にはゆるいけど、まあすぐ消すのでいいかなと。

DBインスタンスにデータを追加

DB作成

console
$ create database omikuji
$ use omikuji
$ create table omikuji.kuji (id int, result varchar(3));

$ insert into kuji values (0,'大吉');
$ insert into kuji values (1,'中吉');
$ insert into kuji values (2,'小吉');

mysql> select * from kuji;
+------+--------+
| id   | result |
+------+--------+
|    0 | 大吉    |
|    1 | 中吉    |
|    2 | 小吉    |
+------+--------+

これで完成

コードを書いていく

node.jsとsequelizeを使ってコマンドライン上でおみくじの結果を出力するようにする。

コマンドラインからディレクトリやファイルを作成したり、serverlessとかsequelizeをインストールしてみたりする。
ファイル構成についてだが、handler.jsにメインの処理を書いて、DBインスタンスのアクセスに必要な情報を.envに置くという構成にする。

console
# ディレクトリの作成
$ mkdir omikuji

# npm初期化
$ npm init -y

# パッケージインストール
$ npm install --save serverless
$ npm install --save sequelize
$ npm install --save dotenv
$ npm install --save mysql2

# serverlessの実行環境作成
$ serverless create --template aws-nodejs 

# ファイルの作成
$ touch .env    // 環境変数用のファイル
$ touch kuji.js // sequelize モデル定義に使うファイル

# ディレクトリ構成は以下の通り
.env                    handler.js              node_modules            package.json
.gitignore              kuji.js                 package-lock.json       serverless.yml

とりあえず、serverlessがちゃんと動くかどうかテストしてみる。.envファイルがあることで警告は出ているが、ちゃんと動いていることが確認できたので、あとはhelloの中身をおみくじができるようにソースコードを変更してあげればよさそう。
※.envによる警告メッセージは話の本筋とは関係ないので、いったん無視していきます。

sls invoke local --function hello
Serverless: Running "serverless" installed locally (in service node_modules)
Serverless: Deprecation warning: Detected ".env" files. Note that Framework now supports loading variables from those files when "useDotenv: true" is set (and that will be the default from next major release)
            More Info: https://www.serverless.com/framework/docs/deprecations/#LOAD_VARIABLES_FROM_ENV_FILES
{
    "statusCode": 200,
    "body": "{\n  \"message\": \"Go Serverless v1.0! Your function executed successfully!\",\n  \"input\": \"\"\n}"
}

ソースコードの修正
.envとhandler.jsを以下のようにする

.env
DATABASE_NAME = "omikuji"
USERNAME = "admin"
PASSWORD = "your_db_password"
HOST =  "mysql-80.xxx.{リージョン}.rds.amazonaws.com"

handler.js
const { Sequelize } = require('sequelize');
require('dotenv').config();

async function hello() {

  const sequelize = new Sequelize(
    process.env.DATABASE_NAME, 
    process.env.USERNAME, 
    process.env.PASSWORD, {
      host: process.env.HOST,
      dialect: "mysql"
  });

  try {
    await sequelize.authenticate();
    console.log('Connection has been established successfully.');
  } catch (error) {
    console.error('Unable to connect to the database:', error);
  } finally {
    sequelize.close();
  }

};

module.exports = { hello }

これで sls invoke local --function helloを実行すると以下のようになるはず。
DBの接続そのものはうまくいったみたいなので、データを取得できるようにしていく。

console
sls invoke local --function hello
Serverless: Running "serverless" installed locally (in service node_modules)
Executing (default): SELECT 1+1 AS result
Connection has been established successfully.

おみくじ機能を実装

おみくじするためのデータ取得処理を作成していく。
コードは以下の通り。

handler.js
const { Sequelize, DataTypes } = require('sequelize');
require('dotenv').config();
const range = 3;

async function hello() {

  // Sequelizeインスタンスの作成
  const sequelize = new Sequelize(
    process.env.DATABASE_NAME, 
    process.env.USERNAME, 
    process.env.PASSWORD, {
      host: process.env.HOST,
      dialect: "mysql",
      logging: false,
  });

  // 0 ... range - 1 の範囲で乱数を生成
  const random = Math.floor( Math.random() * range);

  const Kuji = require("./kuji")(sequelize, DataTypes);

  try {
    const result = await Kuji.findOne({
      where: {
        id: random
      },
      attributes: ["result"],
      raw: true
    })

    return result.result;
  } catch (error) {
    console.error('Unable to connect to the database:', error);
  } finally {
    sequelize.close()
  }
};

module.exports = { hello }

try文でreturnを返したら後の処理ってどうなるんだろうと思ったら、きちんとfinally句は実行してくれるっぽい。(ソース)

kuji.js
module.exports = (sequelize, DataTypes) => {
    return sequelize.define(
      "kuji",
      {
        id: {
          type: DataTypes.INTEGER,
          primaryKey: true,
        },
        result: {
          type: DataTypes.CHAR,
        },
      },
      {
        timestamps: false,
        freezeTableName: true,
      }
    );
};

これで実行してみると...

console
# 1回目
sls invoke local --function hello
Serverless: Running "serverless" installed locally (in service node_modules)
大吉

# 2回目
sls invoke local --function hello
Serverless: Running "serverless" installed locally (in service node_modules)
中吉

できたできた。
あとはこれをlambdaにアップしよう。

Serverless Frameworkのserverless-layersプラグイン

lambdaにアップする前にserverless-layersプラグインを入れて、ライブラリをレイヤーにしてしまおう。

console
$ npx sls plugin install --name serverless-layers

そしたら、レイヤーにするライブラリを格納するためのS3バケットを作成して、そこに格納するようにserverless.ymlに記述していく。あと、デプロイ時にリージョン指定するのも面倒なのであらかじめ設定しておく。

serverless.yml

service: omikuji
frameworkVersion: '2'

provider:
  name: aws
  runtime: nodejs12.x
  region: {お使いのリージョン} # リージョン指定

functions:
  hello:
    handler: handler.hello

custom:
  serverless-layers:
    layersDeploymentBucket: hogehoge # 作成したバケット

plugins:
  - serverless-layers

デプロイ

console
# AWSの認証情報をcredentialsに書き込む
$ serverless config credentials --provider aws --key aws_access_key_id --secret aws_secret_access_key

# デプロイする
$ npx sls deploy 

これでデプロイが完了したので動かしてみる

console
$ sls invoke --function hello
Serverless: Running "serverless" installed locally (in service node_modules)
"小吉"

できた。データベース使っておみくじ作るのは意味わからんが、ひとまずRDSとserverless frameworkを使ってちょっとしたアプリを作れたのでよしとする。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
0
Help us understand the problem. What are the problem?