React + Node + Docker + Postgres (#4 Postgres構築)

DockerでPostgreSQLを起動させ、NodeからSequelizeを利用しアクセスできるようにします。(前回の記事は下記になります)

PostgreSQL構築

Dockerfileを作成します。

mkdir -p ./db/init
touch ./db/Dockerfile.db

Dockerfile.db

FROM postgres:12-alpine
EXPOSE 5432

COPY ./db/init /docker-entrypoint-initdb.d

DB起動時にテーブルを作成するためのファイルを作成します。

touch ./db/init/1_createtable.sql
touch ./db/init/2_insert-task.sql

1_createtable.sql

create table if not exists task(
id       SERIAL PRIMARY KEY,
title         VARCHAR(20),
description   VARCHAR(100),
"createdAt"   TIMESTAMP NOT NULL,
"updatedAt"   TIMESTAMP NOT NULL
);

2_insert-task.sql

INSERT INTO task (title, description, "createdAt", "updatedAt") VALUES ('postgres構築', 'Sequelizeからアクセスする', now(), now());

docker-compose.ymlのservicesにpostgresを追加します。

docker-compose.yml

  postgres:
   build:
     context: .
     dockerfile: ./db/Dockerfile.db
   ports:
     - 5432:5432
   environment:
     POSTGRES_USER: postgres
     POSTGRES_DB: postgres
     POSTGRES_PASSWORD: postgres
   networks: 
     - react-node-docker-postgres

PostgreSQLだけ起動してみます。

docker-compose up --build postgres

PostgreSQLにアクセスしてみます。
taskテーブルが作成されて、データも登録されています。
私は「TablePlus」というDBクライアントを利用しています。

画像2

画像2

SequelizeでPostgreSQLにアクセス

Sequelizeをインストールします。

npm i -D sequelize-cli sequelize pg

PostgreSQLにアクセスするための設定ファイル、JSファイルを作成します。

cd src/app/js
npx sequelize init
npx sequelize model:generate --name task --attributes title:string,description:string

上記のコマンドを実行すると、下記のディレクトリ、ファイルが作成されます。

├── config
│   └── config.json
├── migrations
│   └── 20201015193015-create-task.js
├── models
│   ├── index.js
│   └── task.js
└── seeders

DBの設定を編集します。
./src/app/js/config/config.json

{
 "development": {
   "username": "postgres",
   "password": "postgres",
   "database": "postgres",
   "host": "postgres",
   "dialect": "postgres"
 }
}

このコマンドで作成されるモデルはテーブル名を複数形で扱うので、下記を追加します。
「freezeTableName: true」
./src/app/js/models/task.js

'use strict';
const {
 Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
 class task extends Model {
   /**
    * Helper method for defining associations.
    * This method is not a part of Sequelize lifecycle.
    * The `models/index` file will call this method automatically.
    */
   static associate(models) {
     // define association here
   }
 };
 task.init({
   title: DataTypes.STRING,
   description: DataTypes.STRING
 }, {
   sequelize,
   modelName: 'task',
   freezeTableName: true
 });
 return task;
};

DBにアクセスしてレコードを取得するAPIを追加します。
./src/app/js/main.js

const express = require("express");
const path = require("path");
const db = require('./models/index')

const app = express();

app.get('/api/node', (req, res) => {
 res.send({api: 'Connected Node!'});
})

app.get('/api/docker', (req, res) => {
 const dockerMsg = 'Connected Docker!';
 res.send({docker: dockerMsg});
})

app.get('/api/postgres', (req, res) => {
 db.task.findAll().then(tasks => {
   res.send(tasks);
 });
})

app.listen(3000, ()=> {
 console.log('app running');
})

フロントエンドに追加したAPIを呼び出し、画面に表示できるようにします。

cd ../../../
mkdir ./src/front/js/task
touch ./src/front/js/task/Task.jsx

Task.jsx

import React, { Component } from 'react';
import { getJSON } from "../utils/HttpUtils";

export default class TaskApp extends React.Component {

 state = {
   taskResult: []
 }
   
 componentDidMount() {
   const taskResponseJson = getJSON("/api/postgres")
   .then(taskResponseJson => this.setState({ taskResult: taskResponseJson }));
 }
 
 render() {
   const taskRows = this.state.taskResult.map((task,index) =>
     <tr key={task.id}>
       <td>{task.title}</td>
       <td>{task.description}</td>
     </tr>
   );

   return (
     <div className="TaskApp">
       <table border='1' cellSpacing='0'>
         <thead>
           <tr>
              <th>タイトル</th>
              <th>詳細</th>
           </tr>
         </thead>
         <tbody>
           {taskRows}
         </tbody> 
       </table>
     </div>
   );
 }
}

./src/front/js/main.js

import React from "react";
import ReactDOM from "react-dom";
import NodeApp from './node/Node'
import TaskApp from './task/Task'

const Index = () => {
 return (
   <div>Hello React! <NodeApp /> <TaskApp /></div>
 );
};

ReactDOM.render(<Index />, document.getElementById("root"));

起動すると下記のように表示されます。

画像3

ここまでのものはこちらになります。
https://github.com/YosukeKondo/react-node-docker-postgres/releases/tag/v4.0_postgres

この記事が気に入ったらサポートをしてみませんか?