（古いので参考にしないでください。）nestjsで.envを利用できるようにする。ついでにdockerも

# (古いので参考にしないでください。)nestjsで.envを利用できるようにする。ついでにdockerも

###### Table of Contents

0. 環境作成について
1. configModuleを追加する
2. .envを作成
3. nestjsに.envの設定を読み込ませる
4. dockerに.envを適応する

## 0. 環境作成について

環境作成については、[dockerで簡単にNestJSの環境を作る](https://qiita.com/Gma_Gama/items/def2643aaa7f5f7af41d)と[nestjsとmysqlの接続については](https://qiita.com/Gma_Gama/items/407ad2f121f6d01a6361)を確認いただけるとたすかります。

## 1.configModuleを追加する

nestjsでは[dot-env](https://github.com/motdotla/dotenv#readme)を拡張した[@nestjs/config](https://github.com/nestjs/config)があります。

上記を追加します。

```terminal
$ npm i --save @nestjs/config
```

プロジェクトディレクトリにあるapp.moduleにconfigの読み込みを追加します。

```src/app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';　## ここから追記
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [
## ここから追記
    ConfigModule.forRoot({}),
## ここまで追記
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
```

これで、読み込みは完了です。
次に .env を作成していきます。

## 2. .envを作成

.envをproject directoryの下に追加していきます。
サンプルでは、dbの設定とportを追記します。

```.env
PORT=3000
NODE_ENV=develop

DB_PORT=3306
DB_USERNAME=develop
DB_PASSWORD=password
DB_DATABASE=develop
DB_HOST=db-server
```

先ほど追加したapp.module.tsに簡易的によびこませます。

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

@Module({
  imports: [
    ConfigModule.forRoot({
## ここから追記
      isGlobal: true,
      envFilePath: '.env'
## ここまで追記
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

```

これで読み込みは完了しました。
ついでにenvに読み込ませた、PORTの設定をmain.tsに追記します。
configModuleを追加すると、configServiceを利用することができます。


```src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ConfigService } from '@nestjs/config'; ##ここを追記

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
## ここから追記
  const configService = app.get(ConfigService);
  await app.listen(configService.get('PORT') || 3000);
## ここまで追記
}
bootstrap();
```

以上です。
ここまで十分開発はそこそこできるのですが、
TypeOrmModuleの設定(webpack hotreloadingだとentity読み込まない)と環境別に設定を分けるための設定を保村していきます。

## 3. nestjsに.envの設定を読み込ませる

現状は以下のようなディレクトリで、TypeormModuleを利用していることを想定しています。

```myapp/src
.
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── entity
│   └── user.entity.ts
└── main.ts
```

設定用のconfig.tsを作成src/config以下に設定します。

```terminal
$ mkdir cofig
$ cd config
$ touch configuration.ts
```
作成したconfig/configuration.tsに設定ファイルを読み込ませるように設定を記載します。

```config/configuration.ts

export default () => ({
  port: parseInt(process.env.PORT, 10) || 3000,
  database: {
    type: 'mysql',
    host: process.env.DB_HOST,
    port: process.env.DB_PORT,
    username: process.env.DB_USERNAME,
    password: process.env.DB_PASSWORD,
    database: process.env.DB_DATABASE,
    entities: ['src/**/**.entity{.ts,.js}'],
    synchronize: process.env.NODE_ENV === 'develop' ? true : false,
  },
});

```

次に設定したconfigurationファイルを読み込ませるようにsrc/app.module.tsに読み込ませます。

```src/app.module.ts
import { Module } from '@nestjs/common';
import configuration from './config/configuration';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [
    ConfigModule.forRoot({
## ここから追記
      load: [configuration],
      isGlobal: true,
## ここまで追記
    }),
    TypeOrmModule.forRoot({...}),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
```

load を追加して記載したファイルを読み込ませることができます。
次に、TypeormModuleのdevelop環境の設定をしていきます。
configuration.tsとapp.moudule.tsに設定を追記していきます。

```src/config/configuration.ts
import entities from '../entity';// [ ...Entities ]を想定しています。レポ見てもらうとわかるかも

export default () => ({
  port: parseInt(process.env.PORT, 10) || 3000,
  database: {
    type: 'mysql',
    host: process.env.DB_HOST,
    port: process.env.DB_PORT,
    username: process.env.DB_USERNAME,
    password: process.env.DB_PASSWORD,
    database: process.env.DB_DATABASE,
    entities:
      process.env.NODE_ENV === 'develop'
        ? entities
        : ['src/**/**.entity{.ts,.js}'], //webpack hot reloadingでも読み込むようにinjectします。
    synchronize: process.env.NODE_ENV === 'develop' ? true : false,
  },
});

```

app.module.tsのTypeormModuleに設定を変更していきます。

```src/app.module.ts
import { Module } from '@nestjs/common';
import configuration from './config/configuration';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [
    ConfigModule.forRoot({
      load: [configuration],
      isGlobal: true,
    }),
## ここから編集
    TypeOrmModule.forRootAsync({ //forRootではなく、forRootAsync
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        ...configService.get('database'),
      }),
    }),
## ここまで編集
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

```

以上でwebpackhot-reloadingの時でも読み込むことができます。

## 4. dockerに.envを適応する

以下のようにdocker-compoesファイルに直書きしたことを想定しています。
db-serverに、envfileの読みこみとenvironmentの設定をしていきます。

```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-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'
## ここから追記
    env_file:
      - .env
    environment:
      MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
      MYSQL_DATABASE: '${DB_DATABASE}'
      MYSQL_USER: '${DB_USERNAME}'
      MYSQL_PASSWORD: '${DB_PASSWORD}'
## ここまで追記
```

以上で設定は完了です。
[レポ](https://github.com/Ntakuya/slack-nestjs/tree/feature/environemnt)