Docker+mongodb+nextjsで開発環境を構築してみたよ


Nextjsのexamplesにある、mongooseを使った環境をDockerで構築しました。
https://github.com/vercel/next.js/tree/master/examples/with-mongodb-mongoose

#Docker関連のファイル作成

```bash:bash
touch {Dockerfile,docker-compose.yml,.dockerignore}
```

```docker:Dockerfile
FROM node:15
WORKDIR /app

```

```docker:docker-compose.yml
version: "3"
services:
    node:
        build:
            context: .
        container_name: nodecon
        tty: true
        ports:
            - "3000:3000"
        environment:
            - NODE_ENV=development
            - CHOKIDAR_USEPOLLING=true
        volumes:
            - ./src:/app
    mongo:
        image: mongo
        container_name: mongo-container
        environment:
            - MONGO_INITDB_ROOT_USERNAME=myuser
            - MONGO_INITDB_ROOT_PASSWORD=mypassword
        volumes:
            - mongo-db:/data/db
volumes:
    mongo-db:
```

## dockerを起動する

```bash:bash
docker-compose run --rm node /bin/bash
```

# Nextjsのexampleを取得する
コンテナ内に入れていれば、root@864f3dd6a631:/app# のような表記がターミナルに表示されると思います。
コンテナ内でcreate-next-appを実行する

```bash:bash
npx create-next-app --example with-mongodb-mongoose . 
```

ls で確認するとファイルがいっぱいできた。
localフォルダのsrcにも同じものができていることを確認。

一旦exitでコンテナから抜ける

#.envファイルの作成
src/.env.local.exampleファイルがあると思うので、.envにファイル名を変更し、修正する。
参考[https://docs.mongodb.com/manual/reference/connection-string/]

```.env:.env
MONGODB_URI=mongodb://<username>:<password>@<host>:<port>/test?authSource=admin
```

username,passwordにはdocker-compose.ymlファイルで指定したものを入れる。
ipaddressには、IPアドレスでも良いが、Docker内で名前解決してくれるようなので、サービス名を入れる。
<port>はmongodbのデフォルトポートである、27017を入れる。
今回の例では、以下のようになった。

```.env:.env
MONGODB_URI=mongodb://myuser:mypassword@mongo:27017/test?authSource=admin
```


#Dockerファイルの修正
```diff_docker:Dockerfile
FROM node:15
WORKDIR /app
+ COPY ./src/package.json .
+ ARG NODE_ENV
+ RUN if [ "$NODE_ENV" = "development" ]; \
+     then npm install; \
+     else npm install --production; \
+     fi
```

```diff_docker:docker-compose
version: "3"
services:
    node:
        build:
            context: .
+           args:
+              NODE_ENV: development
        container_name: nodecon
        tty: true
        ports:
            - "3000:3000"
        environment:
            - NODE_ENV=development
            - CHOKIDAR_USEPOLLING=true
        volumes:
            - ./src:/app
+           - /app/node_modules
+       depends_on:
+           - mongo
    mongo:
        image: mongo
        container_name: mongo-container
        environment:
            - MONGO_INITDB_ROOT_USERNAME=myuser
            - MONGO_INITDB_ROOT_PASSWORD=mypassword
        volumes:
            - mongo-db:/data/db

volumes:
    mongo-db:
```

本番環境を見越して環境変数を用意してみた。特になくても良いと思う。
- app/node_modulesはlocalファイルのnode_modulesがなくても良いように設定した。
先にmongodbを起動させるため、depends_onを設定。
# Dockerコンテナの作成

```bash:bash
docker-compose build
```

```bash:bash
docker-compose up -d
```

mongodbとnodeの2つのコンテナが立ち上がっていることを確認

```bash:bash
docker ps
```


### nodeコンテナに入る

```bash:bash
docker exec -it <container_name> /bin/bash
```

ここではnodeのコンテナ名で入る。docker-compose.ymlファイルで指定したコンテナ名nodeconを指定する。

#### nodeコンテナ内でnexjsを起動

```bash:bash
npm run dev
```

http://localhost:3000/ を開いて表示されることを確認

ブラウザで適当にPetを追加する

## DBの確認
### ローカルからdbコンテナに入る

```bash:bash
docker exec -it <db_container_name> /bin/bash
```

### dbにログイン

``` bash:bash
mongo -u <username> -p <password>
```

#### dbを確認
``` bash:bash
> show dbs
```

#### dbの変更
``` bash:bash
> use test
```

#### データの確認
``` bash:bash
> db.pets.find()
```

先ほど入力した値が表示されることを確認。


# 自動的にサーバが立ち上がるよう設定する

毎回 コンテナ内に入って npm run dev は面倒なので、docker-compose up 時に起動するようにする。

```diff_docker:docker-compose.yml
services:
    node:
       ...
        depends_on: 
            - mongo
+       command: npm run dev

```

```bash:bash
docker logs nodecon
```

起動ログが表示されていることを確認。

以上でどないでっしゃろ？