docker上nestjsとmysqlを接続する

# docker上でnestjsとmysqlを接続する

### table of contents

1. nestjsのアプリケーションを作成する
2. localhostで立ち上げる
3. nestjsのアプリケーションをdockerniseする
4. docker-containerでmysqlを利用する
5. typeormを用いてapplicationを接続する

これの続きくらいで考えてくれると助かります。
[dockerで簡単にNestJSの環境を作る](https://qiita.com/Gma_Gama/items/def2643aaa7f5f7af41d)

## 0. 環境

- docker
- nestjs

## 1. nestjsのアプリケーションを作成する

nest g をコマンドを用いてアプリケーションを作成するため、@nest/cliをインストールします。

```terminal
$ npm i -g @nestjs/cli
```

成功すると、

```terminal
$ nest --version
6.12.9
```
でインストールされたバージョンが表示されます。

コマンドが利用できる状況になったところで新規のアプリケーションを作成します。

```terminal
$ nest g application my-app
```

おそらくこんな感じでログが表示されます。

```terminal
CREATE /my-app/.prettierrc (51 bytes)
CREATE /my-app/README.md (3370 bytes)
CREATE /my-app/nest-cli.json (64 bytes)
CREATE /my-app/package.json (1689 bytes)
CREATE /my-app/tsconfig.build.json (97 bytes)
CREATE /my-app/tsconfig.json (336 bytes)
CREATE /my-app/tslint.json (426 bytes)
CREATE /my-app/src/app.controller.spec.ts (617 bytes)
CREATE /my-app/src/app.controller.ts (274 bytes)
CREATE /my-app/src/app.module.ts (249 bytes)
CREATE /my-app/src/app.service.ts (142 bytes)
CREATE /my-app/src/main.ts (208 bytes)
CREATE /my-app/test/app.e2e-spec.ts (630 bytes)
CREATE /my-app/test/jest-e2e.json (183 bytes)
```

一応プロジェクトができているかの確認も込めて、現状のディレクトリ構成を確認

```
$ tree -L 1
.
├── README.md
├── nest-cli.json
├── package.json
├── src
├── test
├── tsconfig.build.json
├── tsconfig.json
└── tslint.json
```

## 2. localhostで立ち上げる

1.で作成されたアプリケーションを用いて、依存packageのインストール、local serverの立ち上げを実施します。

プロジェクトディレクトリに移動して、packageのインストールを実施します。

```
$ cd my-app
$ npm install
```

次にlocalhostを立ち上げます。

```terminal
$ npm run start:dev
12:52:27 AM - Starting compilation in watch mode...


12:52:35 AM - Found 0 errors. Watching for file changes.
[Nest] 51819   - 2020-01-27 12:52:36 AM   [NestFactory] Starting Nest application...
[Nest] 51819   - 2020-01-27 12:52:37 AM   [InstanceLoader] AppModule dependencies initialized +19ms
[Nest] 51819   - 2020-01-27 12:52:37 AM   [RoutesResolver] AppController {/}: +5ms
[Nest] 51819   - 2020-01-27 12:52:37 AM   [RouterExplorer] Mapped {/, GET} route +3ms
[Nest] 51819   - 2020-01-27 12:52:37 AM   [NestApplication] Nest application successfully started +3ms
```

[localhost:3000](http://localhost:3000/)にアクセスすると以下のページが表示されてると思います。

![localhost 3000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144543/d156f83f-1ed8-8456-158b-233ec81d7641.png)

次にdockerniseします。

## 3. nestjsのアプリケーションをdockerniseする

最初にdokcer-compose fileとDockerfileを追加します。

```terminal
$ touch docker-compose.yml
$ touch Dockerfile
```

特段初期装備レベルなので説明は割愛します。

```docker-compose.yml
version: '3.7'
services:
  api-server:
    build: .
    tty: true
    restart: always
    ports:
      - '3000:3000'
    volumes:
      - type: bind
        source: .
        target: /api-server
```

```Dockerfile
FROM node:13.7

RUN npm i -g @nestjs/cli

WORKDIR /api-server
COPY package*.json /api-server/

RUN npm i
CMD [ "npm", "run", "start:dev"]
```

上記の対応で問題ないのですが、一応[nodejsのdockernise](https://nodejs.org/de/docs/guides/nodejs-docker-webapp/)にあるので_.dockerignore_ファイルも追加します。

```terminal
$ touch .dockerignore
```

```.dockerignore
node_modules
dist
```

上記完成するとディレクトリは以下のようになります。

```terminal
$ tree -L 1
.
├── Dockerfile
├── README.md
├── dist
├── docker-compose.yml
├── nest-cli.json
├── node_modules
├── package-lock.json
├── package.json
├── src
├── test
├── tsconfig.build.json
├── tsconfig.json
└── tslint.json

```

次にdocker-composeでdocker-container内のnest serverを立ち上げます。

```terminal
$ docker-compose up --build
```

[localhost:3000](http://localhost:3000/)にアクセスすると以下のページが表示されてると思います。

![localhost 3000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144543/d156f83f-1ed8-8456-158b-233ec81d7641.png)

上記のように表示されたら、mysqlのdocker-containerを立ち上げます。

## 4. docker-containerでmysqlを利用する

docker-containerを追加するため、MySQLを追加していきます。

現状のdocker-compose.ymlはこの通り。

```docker-compose.yml(旧)
version: '3.7'
services:
  api-server:
    build: .
    tty: true
    restart: always
    ports:
      - '3000:3000'
    volumes:
      - type: bind
        source: .
        target: /api-server
```

あたらしく、serviceにmysqlを追加します。(5.X系統なのはまだtypeormが新しいものに対応していなかったからorz)

```docker-compose.yml(新)
version: '3.7'
services:
  api-server:
    container_name: api-server
    build: .
    tty: true
    restart: always
    ports:
      - '3000:3000'
    volumes:
      - type: bind
        source: .
        target: /api-server
#ここから追記
    depends_on:
      - db-server
  db-server:
    container_name: db-server
    image: mysql:5.7.29
    restart: always
    ports:
      - '3306:3306'
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: develop
      MYSQL_USER: develop
      MYSQL_PASSWORD: password
#ここまで追記
```

そして、立ち上げてdocker-container２つがたちあがるか確認します。

```terminal
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
64ec79216641        my-app_api-server   "docker-entrypoint.s…"   3 minutes ago       Up 3 minutes        0.0.0.0:3000->3000/tcp              api-server
0bfe9c3bc2e1        mysql:5.7.29        "docker-entrypoint.s…"   3 minutes ago       Up 3 minutes        0.0.0.0:3306->3306/tcp, 33060/tcp   db-server
```

で上記2つのcontainerがたちあがっていることを確認します。
次は、container同士を接続します。

## 5. typeormを用いてapplicationを接続する

実施するのはこの章のため、[公式ドキュメント](https://docs.nestjs.com/techniques/database)で対応したい方はこっちの方がいいと思います。

やることは一緒で、
1. TypeORMのinstall
2. TypeORMの有効化

を実施していきます。

### 5-1. TypeORMのinstall

依存関係のmoduleをinstallします。

```terminal
$ npm install --save @nestjs/typeorm typeorm mysql
```

### 5-2. TypeORMの有効化

_src/app.module.ts_を編集して、TypeORMを有効化していきます。

現状のapp.module.tsは以下です。

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

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

```

ここにTypeOrmの設定を追記します。

```src/app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; ##ここを追記
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [
##ここから追記
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'db-server',
      port: 3306,
      username: 'develop',
      password: 'password',
      database: 'develop',
      entities: [],
      synchronize: true,
    }),
##ここまで追記
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

```

これでnestjsとmysqlのdockerniseは終わりです。
個人的にはentity系は毎回いらっとするのでいつかちゃんと書きます。

- [れぽ](https://github.com/Ntakuya/slack-nestjs/tree/contents/create-app)
- [環境作成](https://qiita.com/Gma_Gama/items/def2643aaa7f5f7af41d)