Agent Grow Tech Notes
📚

TypeScript & GraphQL でToDoアプリを開発する #2

に公開

⬅️前回の記事はこちら

https://zenn.dev/agent_grow/articles/5eda58d7cb3721

⭐️バックエンドのセットアップ

backend/に移動

% cd ../backend

Node.jsプロジェクトを初期化

% npm init -y

本番用の依存関係をインストール

  • express@4:Node.js用のWebフレームワーク
  • dotenv:.envに設定したポートやキー等を読み込む
  • cors:APIをフロントエンドから安全に呼び出す
  • @apollo/server & graphql & graphql-tag:GraphQLを使うために必要
% npm install express@4 dotenv cors @apollo/server graphql graphql-tag

開発用の依存関係をインストール

  • typescript:.tsを.jsに変換(トランスパイル)する
  • ts-node-dev:.tsをリアルタイムで実行・再起動できる
  • @types/node:Node.jsの型定義 TypeScriptでfs,Path,process 等を使う場合に必要
  • @types/express@4:Expressの型定義 TypeScriptでreq,res,next 等を使う場合に必要
  • @types/graphql:GraphQLの型定義 GraphQLや型を扱う場合に必要
  • @types/cors:corsの型定義
% npm install -D typescript ts-node-dev @types/node @types/express@4 @types/graphql @types/cors

TypeScriptプロジェクトに必要なtsconfig.jsonを作成

% npx tsc --init

backend/の中身を見て、バックエンドの雛形が作られていることを確認

% tree -L 1
.
├── node_modules
├── package-lock.json
├── package.json
└── tsconfig.json

Node.jsにPrisma(ORM)をインストール

  1. 開発中に必要なPrisma CLIをインストール
% npm install -D prisma
  1. Prismaが生成するDBクライアントをインストール
% npm install @prisma/client

Prismaを初期化

% npx prisma init

backend/に下記ファイル、フォルダが作られたのを確認

backend/
├── prisma/
│   └── schema.prisma   // DBスキーマ定義ファイル
├── .env           // 環境変数定義ファイル

作られたschema.prismaを確認

schema.prisma
generator client {                   // Prismaにどんなコードを生成するかを定義するブロック
  provider = "prisma-client-js"      // Prisma公式の JavaScript & TypeScript 用クライアントを使う
  output   = "../generated/prisma"   // コードを生成する出力先ディレクトリを指定(通常は node_modules/@prisma/client に出力されるらしいのでこの記述は削除する)
}

datasource db {                    // どのDBに接続するかを定義するブロック
  provider = "postgresql"          // 使用するDB(今回は postgresql を指定)
  url      = env("DATABASE_URL")   // .envのDATABASE_URLに記載された接続先DBのURLを使う
}

下記のように修正

schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Todo {      // モデル(Todoテーブル)をどのように設計するかを定義するブロック
  id        Int      @id @default(autoincrement())   // idカラム、主キー、1ずつ増える
  title     String                                   // titleカラム
  completed Boolean  @default(false)                 // completedカラム、初期値にfalse
  createdAt DateTime @default(now())                 // createdAtカラム、初期値に現在日時
}

作られた.envを確認

DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"

自身の環境に合うように修正

DATABASE_URL="postgresql://<POSTGRES_USER>:<POSTGRES_PASSWORD>@localhost:<PORT>/tododb?schema=public"

DB用のdocker-compose.ymlをTypeScript-ToDo/に作成

docker-compose.yml
version: "3.8"                                 // Docker Composeのバージョン指定              
services:                                      // コンテナとして動かすサービスを定義する 今回はdbという名前のサービスを定義している
  db:                                          // サービス名
    image: postgres:15                         // PostgreSQL v15 の公式イメージ
    restart: always                            // コンテナが停止するたびに自動的に再起動する
    environment:                               // 環境変数を定義する
      POSTGRES_USER: <POSTGRES_USER>           // <POSTGRES_USER>を.envのDATABASE_URLの値と紐づける
      POSTGRES_PASSWORD: <POSTGRES_PASSWORD>   // <POSTGRES_PASSWORD>を.envのDATABASE_URLの値と紐づける
      POSTGRES_DB: tododb                      // tododbを.envのDATABASE_URLの値と紐づける
    ports:
      - "<PORT>:5432"                         // <PORT>を.envのDATABASE_URLの値と紐づける(ホストの<PORT>にアクセスすると、コンテナ内のPostgreSQL[5432]に届く)
    volumes:
      - db_data:/var/lib/postgresql/data       // 永続化ストレージの設定 ホスト側のdb_dataという名前のボリュームを使って、指定したディレクトリにマウント

volumes:                                       // db_dataボリュームの定義
  db_data:                                     // ボリュームに名前を設定する

コンテナを起動

% docker-compose up -d

DBの接続を確認
※下記コマンドを実行後にパスワードを求められるので、<POSTGRES_PASSWORD>を入力
※確認後はexit

% psql -h localhost -p <PORT> -U <POSTGRES_USER> -d tododb

Prismaでマイグレーションを実行

% npx prisma migrate dev --name init

backend/prisma/に下記ファイル、フォルダが作られたことを確認

backend/prisma/
├── migrations/                // マイグレーション履歴を管理するフォルダ
    ├── 20250601134440_init/   // スキーマ変更の内容が格納されるフォルダ
    │   └── migration.sql      // DBに実行される具体的なSQL文(今回はCREATE TABLE)が書かれたファイル
    └── migration_lock.toml    // マイグレーションの状態を管理するためのロックファイル

🚀バックエンドのセットアップが完了!!!

#2のおわりに

バックエンドのセットアップ お疲れさまでした。
次回からは Apollo Server & Apollo Client の起動 に入っていきます。
https://zenn.dev/agent_grow/articles/8011af2c6d0ec6

〜details tododb(データベース) と db_data(ボリューム)の違いについて〜

◼️tododb
tododbはPostgreSQLの中で使われる、SQLで操作する対象のデータベース名です。

CREATE DATABASE tododb;

上記のような操作をDockerコンテナ起動時に自動的に行うのが下記の定義です。

docker-compose.yml
environment:
  POSTGRES_DB: tododb

◼️db_data
Dockerが管理する、PostgreSQLの物理ファイルが保存される場所(ボリューム)の名前です。
下記の設定により、PostgreSQLのデータが保存される物理フォルダ(/var/lib/postgresql/data)をボリュームにマウントします。

docker-compose.yml
volumes:
  - db_data:/var/lib/postgresql/data

◼️なぜdb_dataで永続化するの?
Dockerコンテナは一時的な実行環境であり、頻繁に作り直すことがあります。
しかし、コンテナを削除するとDB情報(ユーザー情報、テーブル、データ 等)も全て失われてしまいます。
そこで、db_data(ボリューム)を定義しておくことで、コンテナが削除されてもDB情報がホスト側に保持されます。(ボリュームにマウントをすることでバックアップが可能)
新しいコンテナを作る際に、同じdb_dataを定義すればDB情報が復活します。(リストアが可能)

Agent Grow Tech Notes
Agent Grow Tech Notes

Discussion