NestJS+PostgreSQL(+pgAdmin4)の開発環境をDockerで構築する

## はじめに

NestJS + PostgreSQL(+ pgAdmin4)の開発環境を、dockerで構築する手順を紹介します。



## バージョン情報

- Docker : 19.03.13

- Docker Compose  : 1.27.4

- Node.js : 14

- PostgreSQL : 11.2

- pgAdmin4 : 4.2



## ディレクトリ構成

以下のような構成で作成します。

```bash
$ tree -L 2  
.
├── api
│   └── Dockerfile
├── app    // コンテナ共有ディレクトリ
│   └── [ project directory ]
├── db
│   ├── pgadmin4  // DBサーバ接続永続化用ディレクトリ
│   └── postgres  // DBサーバデータ永続化用ディレクトリ
└── docker-compose.yml

```



## Dockerfileの作成

公開されているNode.jsのdockerイメージを使い、PostgreSQLのライブラリを導入します。
ついでにちょっとしたファイル編集用にvimをインストールしておきます。
(主要なファイルは共有フォルダに置くので無くてもよい)

```dockerfile
FROM node:14 
# share directory
ENV ROOT="/app"
# add path env
ENV PATH $PATH:/usr/local/bin
# set home directory
RUN mkdir ${ROOT}
WORKDIR ${ROOT}

RUN apt-get update && apt-get upgrade -y
# install lib (opt : vim)
RUN apt-get install -y build-essential libpq-dev postgresql-client vim
# install NestJS
RUN npm install -g @nestjs/cli
```



## docker-compose.ymlの作成

NestJSアプリケーションを構成するコンテナ情報を記載します。
データベース操作用にpgAdmin4を入れてますが、端末に既に入ってたり、使用しないのであれば要らないです。

```yaml
version: "3.7"

services:
  api:
    build: api
    container_name: nest_api
    tty: true
    ports:
      - "3000:3000"
    volumes:
      - ./app:/app:delegated  # share directory
    links:
      - db
    restart: always

  db:
    image: postgres:11.2
    container_name: nest_db
    ports:
      - "5432:5432"
    volumes:
      - ./db/postgres/init.d:/docker-entrypoint-initdb.d
      - ./db/postgres/pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: root       # DB USER
      POSTGRES_PASSWORD: root   # DB Password
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8"
    hostname: postgres
    user: root
    restart: always

  pgadmin4:
    image: dpage/pgadmin4:4.2
    container_name: pgadmin4
    ports:
      - "8000:80"
    volumes:
      - ./db/pgadmin4:/var/lib/pgadmin
    environment:
      PGADMIN_DEFAULT_EMAIL: root     # pgAdmin Address
      PGADMIN_DEFAULT_PASSWORD: root  # pgAdmin Password
    hostname: pgadmin4
    links:
      - db
    restart: always

```

postgreSQL(pgAdmin4)に設定しているアドレス、パスワードはrootにしてますけど、そこは各自お任せします。



## コンテナを作成&起動する

早速コンテナを作成、および起動します。

```bash
docker-compose build
docker-compose up -d
```

起動後は、一応エラーがないか調べましょう。
(立ち上がらなかったら、原因調査に時間がかなり取られます)

```bash
docker ps -a
// 立ち上がってなかった場合、ログを見て原因調査
docker-compose logs
```



## コンテナにログインする

起動後はコンテナにログインし、プロジェクト作成の準備をします。

```bash
docker-compose exec api bash
//　以下はログインした後にやってます。作業がやりやすいようにしてるだけなので必須ではないです。
echo 'export LS_OPTIONS='\''--color=auto'\' >> ~/.bashrc
echo 'alias ll='\''ls $LS_OPTIONS -l'\' >> ~/.bashrc
source ~/.bashrc
```



## PostgreSQLに接続できるか確認

一応、ちゃんと設定できているか確認。

```bash
psql -h db -U root -d postgres
// rootを入力
Password for user root: 
psql (9.6.19, server 11.2 (Debian 11.2-1.pgdg90+1))
WARNING: psql major version 9.6, server major version 11.
         Some psql features might not work.
Type "help" for help.

// postgresのテーブルにログインできたら成功
postgres=# 
```

ん？なんか警告出てる。
クライアントとサーバ間のバージョン差異での警告みたい。
警告が出るだけで、特に問題ないからヨシ！

※ ヨシじゃねーだろ！って人は以下のコマンドでアップグレードしてください。

```bash
sh -c "echo 'deb http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main' > /etc/apt/sources.list.d/pgdg.list"
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
apt-get update
apt-cache search postgresql | grep ^postgresql
// postgresqlのバージョンが増えてるはずなので、対象のパッケージをインストールします。
// サーバ側を11で入れてるのでクライアントも11をインストールします。
apt-get install -y postgresql-client-11
```



## NestJS新規プロジェクトを作成する

コンテナ内でコマンドを発行します。

```bash
nest new [ New Project Name]
// npm か yarn どっちを使用するか聞かれるので好みの方を選択する。
```



## NestJS起動

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

```bash
cd [ Project directory ]
// npm
npm run start
// yarn
yarn run start
```

起動した後は、実際にブラウザで確認します。
`localhost:3000`にアクセスします。Hello Worldが表示されていたらOK
![](https://storage.googleapis.com/zenn-user-upload/aujnz0ulxpq4ovmevysfd7ovi9km)

## おまけ: pgAdmin4の確認

pgAdmin4も接続確認してみます。
`localhost:8000`でアクセスできます。
![](https://storage.googleapis.com/zenn-user-upload/ys9n312welliuokk5dhyh58esc0e)

アドレスとパスワードは、docker-compose.ymlに書いたrootで入ります。
ログインすると下記のような画面になります。
![](https://storage.googleapis.com/zenn-user-upload/k7qqh5lio1c18flx6xdzk956ob88)

サーバを登録するための設定を行います。
Serversを選択した状態で右クリック→サーバの設定を行います。
![](https://storage.googleapis.com/zenn-user-upload/kj6hxfpkecm15e4rqiac50bf0igc)

サーバ名は自分が分かりやすい名前で。
![](https://storage.googleapis.com/zenn-user-upload/vqif93mdnczc385bp7uz01ympifw)

Connectionタブでホスト名、ユーザ名、パスワードを入力して保存。
![](https://storage.googleapis.com/zenn-user-upload/sghi53psp7gysjf1xae1flpdps3g)

無事に接続できました。
![](https://storage.googleapis.com/zenn-user-upload/vtcbn6j5lh2ntzn3txf8ivi24ifi)


## 最後に

dockerコンテナでNestJSの開発環境を構築しました。
NestJSはAngularに似てるらしいです。
(触ったことがないので私は分かりません。ControllerとServiceはSpringに似てるなぁと思いました)
ここからHTMLを返せるようにするもよし、TypeORMを入れるもよし。
どんどん使っていきましょ〜！


## 参考

[NestJS公式](https://docs.nestjs.com/)
[pgAdmin公式](https://www.pgadmin.org/)
[水無瀬のプログラミング日記 - NestJS事始め](https://minase-program.hatenablog.com/entry/2019/06/07/224619)