DockerでNode×PostgreSQL×Typescript環境を作る

プログラミング

はじめに

今回Dockerを利用して、Node×PostgreSQL×Typescript環境を作るときの手順を解説します。私自身バックエンドエンジニアとしては初学者レベルですが学んだことのアウトプットとして記載したいと思います。主な開発環境としては以下となります。

  • Mac M1
  • Docker version 20.10.11
  • Postgres: 13
  • Node: 14
  • Typescript(4.5.5), Express(4.17.2) <- 今回ここは大して関係ありません

ゴール

今回のゴールはDockerでNode環境、Postgres環境を作成し、http://localhost:3000を叩くと下記のような結果をPostgreSQLを通して取得できるところまでとなります。実際に開発する場合はセキュリティやDB設計、API設計などが重要になってくると思いますが、今回はその辺は特に記載しません。

[
  {
    "id": 1,
    "created_at": "2022-02-05T10:22:44.994Z",
    "updated_at": "2022-02-05T10:22:44.994Z",
    "email": "test@gmail.com",
    "password": "password"
  }
]

またフォルダ構成としては最終的に下記のような形になります。appフォルダ、initdbフォルダ、docker-compose.ymlファイルを作成しておきましょう。

.
├── app
│   ├── Dockerfile
│   ├── package.json
│   └── src
│       └── index.ts
├── docker-compose.yml
└── initdb
    └── setup.sql

Node環境の作成

次にnode環境を作るためにappフォルダに移動して、下記コマンドを打ちましょう。「-y」コマンドはnpm init時に出てくる質問に全てyesで回答するためのコマンドです。今回は特別設定することは無いので、-yをつけています。

cd app
npm init -y

これでpackage.jsonが作られたと思いますので、次は必要なパッケージ類をインストールしましょう。
1行目のexpressはWebアプリケーションを作成するためのフレームワークで、pgはPostgreSQLを利用するためのライブラリとなります。また、2行目はTypescriptを利用するためのライブラリとなります。

npm install --save express pg 
npm install --save-dev typescript ts-node @types/express @types/node @types/pg

次にappフォルダ配下に、src/index.tsファイルを作成し、下記コードを記載しましょう。ある程度コードを見れば分かると思いますが、expressを利用して’/’にリクエストが来た際に、PostgreSQLのusersテーブルを読込、レスポンスとして返すシンプルなルーティングです。

import express from 'express'
import { Pool } from 'pg'
const app: express.Express = express()

const pool = new Pool({
  host: 'postgres',
  database: 'postgres_db',
  user: 'postgres',
  password: 'password',
  port: 5432
})

// ルーティングの設定
app.get('/', async (req, res) => {
  const { rows } = await pool.query('select * from users')
  return res.send(rows)
})

const PORT = 3000
app.listen(PORT, () => {
  console.log(`server started on port ${PORT}`)
})

最後にnodeを実行するために、package.jsonファイルのscriptsの部分に以下を付け足しましょう。これでTypescriptのnodeを実行できます。

"start": "npx ts-node ./src/index.ts"

Docker環境の作成

appフォルダと同じ階層に、docker-compose.ymlを作成したと思いますので、中身に下記を記載しましょう。構成としてはnode環境とpostgers環境を作るためのコードを記載しています。
ちなみに後にinitdb内にsqlファイルを作成しますが、docker-entrypoint-initdb.dという場所にsqlファイルを置くと初期設定時に自動でsqlを実行してくれます。

version: "3.7"
services:
  node:
    container_name: node_express
    build: ./app
    volumes:
      - ./app:/app
    tty:  true
    ports:
      - 3000:3000

  postgres:
    container_name: postgres
    image: postgres:13
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
      POSTGRES_DB: postgres_db
    volumes:
      - db_data:/var/lib/posrgresql/data
      - ./initdb:/docker-entrypoint-initdb.d

volumes:
  db_data: {}

次にappフォルダ内にDockerfileという名前のファイルを作成し、以下を記載しましょう。下記でdocker起動時に[npm run start]コマンドを実行し、nodeを実行するようにしています。

FROM node:14-slim
RUN npm install
WORKDIR /app
CMD ["npm", "run","start"]

初期DB設定

docker作成時にdb設定を行うため、initdbフォルダにsetup.sqlというファイルを作成しましょう。そしてその中に下記を記載しましょう。内容としてはシンプルで、usersテーブルを作成しサンプルとして1つINSERTを行っています。

set
    client_encoding = 'UTF8';

create table users(
    id serial primary key,
    created_at timestamp not null default current_timestamp,
    updated_at timestamp not null default current_timestamp,
    email text not null,
    password text not null
);

INSERT INTO
    users (email, password)
VALUES
    ('test@gmail.com', 'password');

実行してみる

最後に、docker-compose.ymlと同じ階層に戻り下記コマンドを打ちましょう。実行するとimageのダウンロードとdockerコンテナが起動します。

docker-compose up -d

無事に終わりましたら、ブラウザでhttp://localhost:3000を開くと下記が返されるようになったと思います。

[
  {
    "id": 1,
    "created_at": "2022-02-05T10:22:44.994Z",
    "updated_at": "2022-02-05T10:22:44.994Z",
    "email": "test@gmail.com",
    "password": "password"
  }
]

まとめ

Dockerやnodeもまだまだ経験不足でしたが、自在に使えるようになるとかなり便利だなと思いました。次はPrismaなどのORマッパーも利用してみたいと思います。

コメント