LoginSignup
4
5

More than 1 year has passed since last update.

docker-composeでNode.js(Express)とPostgresSQLを連携したサービスを作る勉強会

Last updated at Posted at 2020-06-29

概要

先日行われた勉強会にて簡易ではありますが表題のサービスを作りました。Dockerの勉強の延長で取り組みました。この記事ではそのときの勉強会の内容を記載します。

どんなモノをつくるのか?

  • チャットのようなアプリケーション
  • docker-composeによるデータベースとの連携
    • Node.js(Express)でフロントエンド&バックエンド
    • データベースはPostgresSQL

完成したソースコード

参考にさせていただいた記事

作ったモノの説明

docker-compose

サービス:app

  app:
    build:
      context: ./      # Dockerfile保存場所
    depends_on: 
      - database
    image: n-app                  # イメージ名
    container_name: n-app         # コンテナ名
    ports:                          # ポート接続
      - 3000:5000
    environment:
      PORT: 5000
      DB_USER: postgres
      DB_HOST: database
      DB_PORT: 5432
      DB_NAME: test_db

appNode.js(Express)がメインとなるサービスになります。ここでは学習のために敢えてデフォルトのポートを5000に変更しています。これは参考にさせていただいたExpressの環境変数でPORTが使用されており、それをdocker-compose5000に上書きしています。コンテナ内の5000をホスト側の3000に転送しています。ちなみにExpressで環境変数が使用されている箇所はapp/bin/wwwというファイルで確認できます。

app/bin/www

#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('myapp:server');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
// ~以下省略~

サービス:database

  database:
    image: postgres:12.3
    volumes:
      - ./init-sql:/docker-entrypoint-initdb.d:ro
    environment:
      POSTGRES_DB: test_db
      TZ: "Asia/Tokyo"
      POSTGRES_HOST_AUTH_METHOD: trust

databasePostgresSQLを使用しています。docker-composeで環境変数であるPOSTGRES_DBtest_dbに設定することで自動的にtest_dbという名前のデータベースが作成されます。

volumesの設定はinit-dbというフォルダにSQLファイルを格納しておくことで、SQLファイルに書かれているクエリを自動的に実行してくれます。
初期スキーマの設定(テーブル構造の作成)やダミーデータなどを挿入するときに利用します。

実行順序はファイル名の昇順で実行されるので、ファイル名に番号などをつけるとよさそうです。

今回、作成したデータベースにはpostgresというユーザーが作成されますが、パスワードが設定されていません。そのためPOSTGRES_HOST_AUTH_METHODtrustに設定する必要があります。

あと、TZでタイムゾーンを設定しています。タイムゾーンの変更については以下のクエリでも可能です。

ALTER DATABASE test_db SET timezone TO 'Asia/Tokyo';
SELECT pg_reload_conf();

init-dbにクエリをファイルとして格納しておけばタイムゾーンも変更可能です。ただし、どこでタイムゾーンが設定されているか後追いしづらいので、環境変数で設定できるなら環境変数を使った方が良いと思います。

Dockerfile:Node.js(Express)

今回のアプリケーションの部分(サービス:app)はappフォルダ配下
Expressのソースが格納されています。それらのソースを元にDockerfileでコンテナを作成します。

Dockerfile

# ベースイメージを指定
FROM node:10.12

# 環境変数設定
ENV NODE_ENV="development"

# 作業ディレクトリ作成&設定
WORKDIR /src

COPY ./app /src

RUN npm install

CMD npm run start

ここで重要なのでコンテナの中にsrcというフォルダを作成し、そこにホスト(自分の端末)のappフォルダの中身をコピーします。srcWORKDIRに設定されているのでsrcでコピーしたソースファイルを元にnpm installなどを実行できます。

今回はDockerfileでソースをコピーしましたがdocker-composeでも同じようなことが可能です。

Node.js(Express)

ここは別記事にしてもよいくらい説明する箇所が多いので抜粋して記載します。今回のExpressのソースではapp/routesフォルダのファイルでエンドポイントを設定して、表示内容をapp/viewsフォルダのテンプレートのファイルに渡してコンテンツを表示する流れになっています。

処理の流れ
app/routes → app/views

localhost:3000 にアクセス

app/routes/index.js
↓
app/views/index.ejs

index.jsではPostgresSQLchatテーブルをセレクトした結果をindex.ejsに渡しています。

localhost:3000/insert?msg=SEND_TEST

app/routes/insert.js
↓
app/views/index.ejs

insert.jsではURLパラメーターでmsgを受け取ることができます。msgの値をchatテーブルにインサートします。もしパラメーターがない場合は「ふにょふにょ」という値がインサートされます。

表示する内容はindex.ejsと同じですがインサートされた後のテーブルの情報を表示します。app/routesのファイルとapp/viewsのファイルは必ず1対1にする必要はなく、同じテンプレートでも渡す内容で表示内容を切り替えるなどの制御も可能だったりします。

データベース(PostgresSQL)への接続:db_client.js

module.exports = {
    pg_client: function () {
        const { Client } = require('pg')

        const client = new Client({
            user: process.env.DB_USER,
            host: process.env.DB_HOST,
            port: process.env.DB_PORT,
            database: process.env.DB_NAME
        })
        return client
    },
    pupupu: function () {
      console.log('pupupupu')
    }
  };

db_client.jsでデータベースの接続処理を共通で使用できるようにしています。PostgresSQLに必要なユーザー情報などはdocker-composeから環境変数で受け取りそれを元に接続を行います。

総評

ある程度コンパクトにまとまっており、構成もそこまで複雑ではないかなと思いました。ただ開発するときに少し難がありExpressは個別でnpm installなどでpackage.jsonなどを更新する必要があります。これはdocker-compose buildappフォルダをコピーしているので、アプリのnode_moduleなどは手動で更新しないとコンテナで動作してくれません。逆にnpm startなどで開発すればよい話になりますが、データベースとの接続ができないので困ったところです。
しかしながら、今回の勉強会ではいろいろとdocker-composeについて理解を深めることができたのでよかったかなと思います。

4
5
0

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
4
5