Next.js、json-server、storybookの開発環境をコンテナ上に構築

# はじめに
書籍「[TypeScriptとReact/Next.jsでつくる実践Webアプリケーション開発](https://www.amazon.co.jp/TypeScript%E3%81%A8React-Next-js%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8B%E5%AE%9F%E8%B7%B5Web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%96%8B%E7%99%BA-%E6%89%8B%E5%B3%B6-%E6%8B%93%E4%B9%9F/dp/4297129167)」でアプリを開発する際に、開発環境をコンテナ上に構築することにしました。

私自身Dockerfileやdocker-compose.ymlを一から記述することをあまり経験したことがないため、学習を兼ねて独自に作成してます。

メモ書き程度ですが参考になれば幸いです。


# 目的

- 個人に依存せず、再現性の高い開発環境を構築
- コンテナのボリュームマウントの仕組みを理解
- コンテナ間で通信可能なネットワーク設定

# 構築

- Next.jsアプリケーション
- storybook
- json-server（ダミーAPIサーバー）

# ディレクトリ構造
```
workspace
├── docker
│   └── compose.yml
├── json-server            // json-serverのソースディレクトリ
│   └── docker
│       └── Dockerfile
└── ts-nextbook-app-main   // Next.jsアプリケーションのソースディレクトリ
    ├── docker
    ├── .storybook         // storybookのソースディレクトリ
    └── .env
```
# ファイル内容

- .env

```
API_BASE_URL=http://172.30.0.4:8000     // json-serverのIPアドレス
NEXT_PUBLIC_API_BASE_PATH=/api/proxy
```

- ts-nextbook-app-main/docker/Dockerfile

```
FROM node:18.12-alpine

WORKDIR /ts-nextbook-app-main/

COPY ts-nextbook-app-main/package.json ./
COPY ts-nextbook-app-main/package-lock.json ./

RUN npm update && npm ci
```

- json-server/docker/Dockerfile

```
FROM node:18.12-alpine

WORKDIR /json-server/

COPY json-server/db.json ./
COPY json-server/package-lock.json ./
COPY json-server/package.json ./
COPY json-server/server.js ./

RUN npm update && && npm ci
```
- docker/compose.yml

```
services:
  nextjs-gihyo-book:
    build:
      context: ../
      dockerfile: ts-nextbook-app-main/docker/Dockerfile
    ports:
      - "12000:3000"
    volumes:
      - ../ts-nextbook-app-main:/ts-nextbook-app-main
      - node_modules:/ts-nextbook-app-main/node_modules
    command: sh -c "npm run dev"
    networks:
      app_net:
        ipv4_address: 172.30.0.2
    depends_on:
      json-server:
        condition: service_started

  story-book:
    build:
      context: ../
      dockerfile: ts-nextbook-app-main/docker/Dockerfile
    ports:
      - "13000:6006"
    volumes:
      - ../ts-nextbook-app-main:/ts-nextbook-app-main
      - node_modules:/ts-nextbook-app-main/node_modules
    command: sh -c "npm i --save-dev @storybook/cli && npm run storybook"
    networks:
      app_net:
        ipv4_address: 172.30.0.3

  json-server:
    build:
      context: ../
      dockerfile: json-server/docker/Dockerfile
    ports:
      - "14000:8000"
    volumes:
      - ../json-server/node_modules:/json-server/node_modules
    command: sh -c "npm start"
    networks:
      app_net:
        ipv4_address: 172.30.0.4
volumes:
  node_modules:
networks:
  app_net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.30.0.0/24

```

- Port 12000：Next.js
- Port 13000：storybook
- Port 14000：json-server
- ネットワークサブネット：172.30.0.0/24
- ローカルのnode_modulesやファイル群をworkdirにマウント
- json-serverの起動後にNext.jsアプリケーションを起動（depends_on）


# 起動

```sh
docker compose build       // イメージのビルド
docker compose up -d       // コンテナの起動
docker compose down        // コンテナの停止

http://localhost:12000     // アプリケーション
http://localhost:13000     // storybook
http://localhost:14000     // json-server
```

# あとがき

コンテナ内のネットワークにIPアドレスを指定せずに接続する方法があればその方がベターですね。
あとはコンテナ起動時にstorybookのCLIがインストールされていない？ようなので、commandで無理やりインストールしてます。。npm ciだけでは上手くいかないのでこちらも調べてみます。

もう少し動かせるようになったらKubernetesも触ってみたい。

最後まで読んでいただきありがとうございました。