はじめに
AWSの使っておみくじアプリを作るよ(そんなのRDSを使わなくてもよくね?という話はナシで)
環境
node.js v12.18.3
作ってみる
DBインスタンスの作成
ここを参考にRDSを使ってDBインスタンスを作成していく
DBの設定
- データベース作成方法:簡単作成
- 設定:MySQL
- インスタンスサイズ:無料利用枠
- DBインスタンス識別子:aws-web-service
- マスターユーザー名:admin
- マスターパスワード:各自おまかせ
- パブリックアクセス可能:あり
作成したDBインスタンスのエンドポイントとマスターユーザーを使ってDBインスタンスにアクセス。
mysql -h mysql-80.xxx.{リージョン}.rds.amazonaws.com -P 3306 -u admin -p
RDSをパブリックアクセス可能にしてるのでセキュリティ的にはゆるいけど、まあすぐ消すのでいいかなと。
DBインスタンスにデータを追加
DB作成
$ 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に置くという構成にする。
# ディレクトリの作成
$ 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を以下のようにする
DATABASE_NAME = "omikuji"
USERNAME = "admin"
PASSWORD = "your_db_password"
HOST = "mysql-80.xxx.{リージョン}.rds.amazonaws.com"
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の接続そのものはうまくいったみたいなので、データを取得できるようにしていく。
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.
おみくじ機能を実装
おみくじするためのデータ取得処理を作成していく。
コードは以下の通り。
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句は実行してくれるっぽい。(ソース)
module.exports = (sequelize, DataTypes) => {
return sequelize.define(
"kuji",
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
},
result: {
type: DataTypes.CHAR,
},
},
{
timestamps: false,
freezeTableName: true,
}
);
};
これで実行してみると...
# 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プラグインを入れて、ライブラリをレイヤーにしてしまおう。
$ npx sls plugin install --name serverless-layers
そしたら、レイヤーにするライブラリを格納するためのS3バケットを作成して、そこに格納するように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
デプロイ
# AWSの認証情報をcredentialsに書き込む
$ serverless config credentials --provider aws --key aws_access_key_id --secret aws_secret_access_key
# デプロイする
$ npx sls deploy
これでデプロイが完了したので動かしてみる
$ sls invoke --function hello
Serverless: Running "serverless" installed locally (in service node_modules)
"小吉"
できた。データベース使っておみくじ作るのは意味わからんが、ひとまずRDSとserverless frameworkを使ってちょっとしたアプリを作れたのでよしとする。