2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Docker Compose】NestJS / TypeScript / MySQL の開発環境構築

Posted at

はじめに

この記事では、Docker Compose を利用した NestJS / TypeScript / MySQL の開発環境構築手順について記載します。

開発環境

開発環境は以下の通りです。

  • Windows11
  • Docker Engine 26.1.1
  • Docker Compose 2
  • Node.js 20.15.1
  • NestJS 10.0.0
  • TypeScript 5.1.3
  • MySQL 9.0.0
  • MySQL2 3.11.0
  • TypeORM 0.3.20\

NestJS / TypeScript の環境構築

まずは NestJS アプリケーションの開発支援ツールである Nest CLI をインストールします。

 npm i -g @nestjs/cli

次に以下のコマンドでプロジェクトを作成します。
nest-mysql はプロジェクト名です。また、--strict を追加することで、TypeScript の strict 系のコンパイラオプションが有効になります。

nest new nest-mysql --strict

パッケージマネージャーは npm を利用します。

  We will scaffold your app in a few seconds..

? Which package manager would you ❤️  to use? npm
CREATE nest-mysql/.eslintrc.js (688 bytes)
CREATE nest-mysql/.prettierrc (54 bytes)
CREATE nest-mysql/nest-cli.json (179 bytes)
CREATE nest-mysql/package.json (2018 bytes)
CREATE nest-mysql/README.md (3413 bytes)
CREATE nest-mysql/tsconfig.build.json (101 bytes)
CREATE nest-mysql/tsconfig.json (562 bytes)
CREATE nest-mysql/src/app.controller.ts (286 bytes)
CREATE nest-mysql/src/app.module.ts (259 bytes)
CREATE nest-mysql/src/app.service.ts (150 bytes)
CREATE nest-mysql/src/main.ts (216 bytes)
CREATE nest-mysql/src/app.controller.spec.ts (639 bytes)
CREATE nest-mysql/test/jest-e2e.json (192 bytes)
CREATE nest-mysql/test/app.e2e-spec.ts (654 bytes)

 Installation in progress... 

🚀  Successfully created project nest-mysql
👉  Get started with the following commands:

$ cd nest-mysql
$ npm run start


                          Thanks for installing Nest 🙏
                 Please consider donating to our open collective
                        to help us maintain this package.


               🍷  Donate: https://opencollective.com/nest

プロジェクトを作成したディレクトリに移動します。

cd nest-mysql

ローカルサーバーを起動します。

npm start

プロジェクト作成時に自動生成されたコードの中に 'Hello World!' を返す getHello メソッドがあるので、動作確認します。

image.png

NestJS の Dockerfile 作成

次は NestJS の Dockerfile を作成します。

# Use the official Node.js image
FROM node:20-alpine3.19

# Create and set the working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Expose the application port
EXPOSE 3000

# Run the application
CMD ["npm", "start"]

動作確認のため、作成した Dockerfile を利用したイメージのビルドとコンテナの起動確認をします。
まずはイメージをビルドします。

docker image build --tag nest-ts:1.0.0 .

image.png

イメージがビルドできたか確認します。

docker image ls nest-ts

image.png

ビルドしたイメージを使ってコンテナを起動します。また、コンテナ起動時にホストマシンのファイルをバインドマウントします。

docker container run                          `
--name nest-ts                                `
--rm                                          `
--publish 3000:3000                           `
--mount type=bind,source="$(pwd)",target=/app `
nest-ts:1.0.0

NestJS のプロジェクトファイル作成時と同じく getHello メソッドを呼び出して動作確認をします。

image.png

compose.yaml と DB 初期データ作成ファイルの作成

以下の要件を満たす compose.yaml を作成します。

  • NestJS
    • コンテナ名:app-container
    • ビルド:Dockerfile
    • ポート:3000
    • ソースコード:ホストマシンで実装
  • MySQL
    • コンテナ名:db-container
    • ビルド:MySQL 公式イメージのタグ 9.0.0
    • ポート:3306
    • 初期データを用意
    • データはコンテナを削除しても残す
    • ホストマシンからDB接続可能
  • コンテナ間通信可能
compose.yaml
services:
  app:
    container_name: 'app-container'
    build: . # Dockerfile path
    ports:
      - '3000:3000'
    volumes:
      - type: bind
        source: ./
        target: /app
    environment:
      DB_HOST: db
      DB_USER: user
      DB_PASSWORD: userpassword
      DB_NAME: sampledb
  db:
    container_name: 'db-container'
    image: mysql:9.0.0
    ports:
      - '3306:3306'
    volumes:
      - type: bind
        source: ./db
        target: /docker-entrypoint-initdb.d
      - type: volume
        source: db-volume
        target: /var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: sampledb
      MYSQL_USER: user
      MYSQL_PASSWORD: userpassword
volumes:
  db-volume:

DB の初期データ作成ファイルのバインドマウント先の値 /docker-entrypoint-initdb.d は、Docker Hub の MySQL リポジトリの Initializing a fresh instance に記載があります。1

DB のボリュームマウント先の /var/lib/mysql は、MySQL サーバーがデータを保存するデフォルトのディレクトリになります。MySQL 設定ファイル(/etc/my.cnf)で定義されています。

docker container run --rm mysql:9.0.0 cat /etc/my.cnf
[mysqld]
...
datadir=/var/lib/mysql
...

バインドマウント元の DB 初期データ作成ファイルを作成します。

db/init-users.sql
CREATE TABLE users(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(32) NOT NULL, email VARCHAR(32) NOT NULL);
INSERT users (name, email) VALUES ("Wyatt", "wyatt@example.com");
INSERT users (name, email) VALUES ("Billy", "billy@example.com");

ここまでできたら一度動作確認をします。

docker compose up --build

コンテナ一覧を確認します。

docker container ls

compose.yaml で定義した名前通りのコンテナが作成されています。

image.png

App コンテナの動作確認として、今回も getHello メソッドを呼び出して動作確認をします。

image.png

DB コンテナの動作確認として、初期データが登録されているか確認します。
まずは MySQL に接続します。

mysql --host=127.0.0.1 --port=3306 --user=user --password=userpassword

データベース一覧に環境変数として指定したデータベースが存在することを確認します。

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| performance_schema |
| sampledb           |
+--------------------+
3 rows in set (0.08 sec)

初期データ作成時に指定したテーブル及びユーザーデータがあることを確認します。

mysql> use sampledb;
Database changed
mysql> select * from users;
+----+-------+-------------------+
| id | name  | email             |
+----+-------+-------------------+
|  1 | Wyatt | wyatt@example.com |
|  2 | Billy | billy@example.com |
+----+-------+-------------------+
2 rows in set (0.04 sec)

この時点では、AppコンテナとDBコンテナがそれぞれ起動しているだけで、コンテナ間の通信は発生していません。

DB 接続処理の実装

App コンテナ(NestJS)から DB コンテナへの接続処理を実装します。

パッケージのインストール

必要なパッケージをインストールします。

  • MySQL2 : MySQL クライアント
  • TypeORM : TypeScript / JavaScript 向けの ORM(DB とプログラミング言語のデータ変換)
  • @nestjs/typeorm : NestJS 向けの TypeORM モジュール

npm install --save @nestjs/typeorm typeorm mysql2

TypeORM の設定

先ほどインストールした TypeORM の設定ファイルを作成します。

src/ormconfig.ts
import { TypeOrmModuleOptions } from '@nestjs/typeorm';

const config: TypeOrmModuleOptions = {
  type: 'mysql',
  host: 'db',
  port: 3306,
  username: 'user',
  password: 'userpassword',
  database: 'sampledb',
  entities: [],
  synchronize: true,
};

export default config;

作成した設定値を src/app.module.tsimportsTypeORMModule.forRoot の引数として渡します。

src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import config from './ormconfig';

@Module({
  imports: [TypeOrmModule.forRoot(config)], // Add
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

アプリ初期化時にクエリを実行する

設定ができたので、実際 DB に接続する処理を追加します。
今回はアプリ初期化時に簡単なクエリを実行します。

src/app.module.ts
import { Module, OnModuleInit } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { InjectDataSource, TypeOrmModule } from '@nestjs/typeorm';
import config from './ormconfig';
import { DataSource } from 'typeorm';

@Module({
  imports: [TypeOrmModule.forRoot(config)],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule implements OnModuleInit {
  constructor(@InjectDataSource() private readonly dataSource: DataSource) {}

  async onModuleInit() {
    try {
      await this.dataSource.query('SELECT 1');
      console.log('Database connection is successful');
    } catch (error) {
      console.error('Error connecting to the database', error);
    }
  }
}

動作確認

Docker を起動して動作確認をします。

docker compose up --build

先ほど実装したログ Database connection is successful が出力されます。

image.png

参考

  1. https://hub.docker.com/_/mysql

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?