Express.js + Sequelize ORM + PostgreSQL を使って Heroku にデプロイ

組み合わせることで Node.js を使った MVC アプリを気軽に Web サーバーにデプロイすることが可能です。この記事ではコードはあまり書かずにコマンドや設定ファイルだけで進む簡単な内容になっているため、前提条件さえクリアできればジュニアソフトウェアエンジニアでも理解できると思います。運用は無視した勉強用の記事です。

## アーキテクチャ

[![Image from Gyazo](https://i.gyazo.com/9cfcefa05406d02817e726d7ffdb51d3.png)](https://gyazo.com/9cfcefa05406d02817e726d7ffdb51d3)

完成版のソースコードは [KtoZ/sample-expressjs-sequelize-postgresql-heroku](https://github.com/KtoZ/sample-expressjs-sequelize-postgresql-heroku) に置いてあります。

## 前提条件

これらがインストールされていて使用可能な状態になっていること。

- Node.js
- Heroku Account (Free)
- Heroku CLI
  - [Getting Started on Heroku with Node.js | Heroku Dev Center](https://devcenter.heroku.com/articles/getting-started-with-nodejs#set-up)
- Docker
  - PostgreSQL の起動に使用します。 Docker の代わりに PostgreSQL 本体をインストールしても問題ありません。
- Git

## 開発

アプリを開発してローカル環境で実行するまでを進めていきます。

### Express.js の構築

Express generator 使って作業ディレクトリに express のテンプレートを作成します。この記事では View を書かずに進めるため View エンジンはなんでもよいです。

```shell
npm install express-generator -g
express
npm install
```

作成後は `npm start` コマンドを実行することで、ブラウザなどから [localhost:3000](http://localhost:3000) にアクセス可能になります。

### Docker を使用した PostgreSQL の構築

PostgreSQL を構築するための _docker-compose.yml_ を作業ディレクトリに追加します。ユーザーやパスワードなどは自由に変更して問題ありません。

```yaml:./docker-compose.yml
version: "3"

services:
  postgresql:
    image: postgres:12-alpine
    container_name: postgresql
    ports:
      - 5432:5432
    volumes:
      - db_data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: hoge123
      POSTGRES_DB: root
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=ja_JP.UTF-8"
    hostname: postgres
    restart: always
    user: root
volumes:
  db_data: {}
```

_docker-compose.yml_ を追加したら `docker-compose up -d` コマンドを実行することで PostgreSQL が起動します。終了したいときは `docker-compose down` コマンドを実行してください。

### Sequelize でテーブル作成

アプリから PostgreSQL に接続するためのパッケージと、 Sequelize ORM を使用するためのパッケージをインストールします。

```
npm install --save pg pg-hstore sequelize sequelize-cli
```

Sequelize CLI を使用して Sequelize ORM を初期化します。初期化が完了すると作業ディレクトリに _config.json_ や _models_ ディレクトリが作成されます。

```
npx sequelize-cli init
```

データベースへの接続設定が書かれている _config/config.json_ を開いて development 設定を書き換えます。

```json:./config/config.json
  "development": {
    "username": "root",
    "password": "hoge123",
    "database": "root",
    "host": "127.0.0.1",
    "dialect": "postgres",
    "operatorsAliases": false
  },
```

Sequelize CLI を使用して新しいテーブルモデルを作成します。作成が完了すると _models_ ディレクトリに _user.js_ ファイルが作成されます。この記事では user テーブルを作成しています。

```
npx sequelize-cli model:generate --name user --attributes firstName:string,lastName:string,email:string
```

Sequelize CLI を使用してデータベースにテーブルを作成します。マイグレーションコマンドを実行することによって、作成したモデルがテーブルとして追加されます。コマンド実行後にデータベースへ接続してテーブルが作成されていることを確認してみてください。

```
npx sequelize-cli db:migrate
```

### Express.js からテーブルに接続して値を返す

_routes/users.js_ を開いてコードをこのように置き換えます。テーブルに登録されている全てのレコードを返却しています。

```js:./routes/users.js
var express = require("express");
var router = express.Router();
let db = require("../models/index");

/* GET users listing. */
router.get("/", function (req, res, next) {
  db.user.findAll({}).then((users) => {
    res.send(users);
  });
});

module.exports = router;
```

### 実行確認

テーブルに適当なレコードを追加したあとに `npm start` でアプリを実行して、ブラウザから [localhost:3000/users](http://localhost:3000/users) にアクセスしてください。追加したレコードが全て画面に表示されていることが確認できます。

[![Image from Gyazo](https://i.gyazo.com/061575e02b07ebf7de38a182f6675c08.png)](https://gyazo.com/061575e02b07ebf7de38a182f6675c08)

## デプロイ

アプリを Heroku サーバーにデプロイして本番環境で実行するまでを進めていきます。

### Git の初期化

Heroku にデプロイするときは Git を使用します。そのため、現在の作業ディレクトリを Git 化にします。

```
git init
```

.gitignore ファイルを作業ディレクトリに作成します。内容は簡素化しています。きちんとしたものを使用したい場合は [gitignore/Node.gitignore at master · github/gitignore](https://github.com/github/gitignore/blob/master/Node.gitignore) を参考にしてください。

```txt:./.gitignore
node_modules/
```

### Heroku のサーバー構築

Heroku CLI を使用してログインします。その後、サーバーとデータベースの作成を実行します。サーバー作成時に Heroku にデプロイするための Git Remote 設定がされます。

```shell
heroku login
heroku create
heroku addons:create heroku-postgresql:hobby-dev

# Git Remote 確認用のコマンド
git remote -v
# heroku  https://git.heroku.com/polar-retreat-04355.git (fetch)
# heroku  https://git.heroku.com/polar-retreat-04355.git (push)
```

### アプリの本番環境設定

_config/config.json_ を開いて production 設定を書き換えます。 Heroku はサーバーでアプリを実行するときに production 設定を使用します。 `"use_env_variable": "DATABASE_URL"` を設定することで Heroku で作ったデータベースを使用するようになります。

```json:./config/config.json
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "postgres",
    "operatorsAliases": false,
    "use_env_variable": "DATABASE_URL"
  }
```

### アプリと DB のデプロイ

アプリをデプロイするためのコードをコミットします。

```shell
git add .
git commit -m "Add Application"
```

Heroku にアプリをデプロイします。

```
git push heroku master
```

Heroku CLI を使用して Heroku データベースにテーブルを作成します。

```shell
# Heroku Terminal に接続
heroku run bash

# データベースマイグレーションを実行
sequelize db:migrate

# Heroku Terminal から切断
exit
```

### 実行確認

Heroku CLI でデプロイしたアプリをブラウザで開きます。アプリが開いたら _/users_ にアクセスして、データベースに登録されているレコードが帰ってくることを確認します。 ※画像はレコードが何もない状態です。

```shell
heroku open
# Open https://<YOUR_APP_NAME>.herokuapp.com/
```

[![Image from Gyazo](https://i.gyazo.com/0c397dfd2177445b0990e09ba590f383.png)](https://gyazo.com/0c397dfd2177445b0990e09ba590f383)