docker-composeで react-create-appのサーバをワンコマンドで実行する

# docker-composeで react-create-appのサーバをワンコマンドで実行する

docker-composeでreact-create-appを扱いたかったのでやり方をまとめます。
apiサーバとclientでコンテナを分けたいケースに便利です。

今回は1コマンドでサーバが立ち上がるところまでを目標にします。



ベースはこの記事を参考にしています。

[Docker環境内でcreate-react-app@@mii288](https://qiita.com/mii288/items/aac597bc02575831ea90)

# TL;DR

`docker-compose` を使い `react-create-app` でサーバをワンコマンドで実行します。

dockerコンテナ内でのWORK DIRはお任せします。

初期状態のディレクトリツリーはこんな感じです。以下のようにファイルを配置してください。

```
── docker-compose.yml
└── ui
    └── Dockerfile.ui
```

`docker-compose.yml`, `Dockerfile` は以下。


```yml
# docker-compose.yml
version: "3"
services:
  ui:
    build:
      context: ./ui 
      dockerfile: Dockerfile.ui
    volumes:
      - ./ui:/your/path/ui 
    ports:
      - 127.0.0.1:3000:3000 
    command: sh -c "yarn create react-app ./my-app && \
                    cd ./my-app && \ 
                    yarn start"

```

```dockerfile
# Dockerfile.ui
FROM node:13.7.0
WORKDIR /your/path/ui 
```

実行するコマンドは以下。

```sh
// 起動
$ docker-compose up --build -d ui
```

以下は個々の解説です。

# dockerfileの解説


```dockerfile
# Dockerfile.ui
FROM node:13.7.0
# docker-compose.ymlのvolumesと合わせると良いです
WORKDIR /your/path/ui 
```

dockerhubからnodeのイメージを持ってきて使います。yarnはすでにインストールされています。

`WORKDIR` は 環境に合わせて設定してください。

このディレクトリは `docker-compose.yml` にも登場します

# docker-composeの解説

```yml
# docker-compose.yml
version: "3"
services:
  ui:
    build:
      context: ./ui # ui dirのdockerfileを読みにいく
      dockerfile: Dockerfile.ui
    volumes:
      - ./ui:/your/path/ui # ホストのui dirを /your/path/uiに同期
    ports:
      - 127.0.0.1:3000:3000 # dockerコンテナの3000番をホストの3000番にbind
    command: sh -c "yarn create react-app ./my-app && \ #  react-create-appを作成
                    cd ./my-app && \ # dirに移動
                    yarn start" # package.jsonで指定されたserverの起動

```


`docker-compose` は複数のdockerコンテナ(仮想マシン)を協調させて動かすためのツールです。
なので1つだけコンテナを扱うならdockerだけで十分です。

(その方法を知りたい方は [Docker環境内でcreate-react-app@mii288](https://qiita.com/mii288/items/aac597bc02575831ea90)
 を参考にしてください。こちらの方が丁寧です。)


今回は `ui` というサービスを作ります。

```yml
services:
  ui:
```

## build


```yml
    build:
      context: ./ui # ui dirのdockerfileを読みにいく
      dockerfile: Dockerfile.ui
```

`ui/build/context` で dockerコンテナの build 作業用ディレクトリを決めます。
`ui/build/dockerfile` で `./ui/Dockerfile.ui` を読み込みコンテナをビルドしてくれます。

## volumes

```yml
    volumes:
      - ./ui:/your/path/ui # ホストのui dirを /your/path/uiに同期
```

`ui/volumes` は ホストマシンのディレクトリと、コンテナ上のディレクトリをマウント(同期)するための機能です。
 `docker-compose.yml` が置かれたディレクトリをカレントディレクトリとしてパスを指定します。

`ホストマシンのpath:コンテナのpath` のように設定を行います。

今回はホストマシンの `./ui` を コンテナ上の `/your/path/ui` に同期します。

`DockerfileのWORKDIR` と揃えましょう。

## ports とポートフォワーディング

この設定をしないと、 `サーバーは生きているけどリクエストが届かない` 状態になります。


```yml
ports:
      - 127.0.0.1:3000:3000 # dockerコンテナの3000番をホストの3000番にbind
```

`react-create-app` のサーバはデフォルト3000番で立ち上がるのでこうしています。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33830/94a883a9-fb03-4832-8a1a-472d304c0890.png)

(画像は[@mii288](https://qiita.com/mii288/items/aac597bc02575831ea90)さんの記事からお借りしました)

ホストマシンの `ipアドレス:ポート` と コンテナの `ipアドレス:ポート` をbindします。

以下のように設定を行います。

```
ホストip:ホストport:(コンテナip):コンテナport # コンテナipは省略
```

今回は ホストマシンの `127.0.0.1:3000` を コンテナの`3000番` にbindします。



仮想マシン上のネットワークとホストマシン上のネットワークを付き合わせるための設定です。
(`ポートフォワーディング`)

ローカルホストの `127.0.0.1:3000` にリクエストを送ると、dockerコンテナ上で `3000番` で待っているサーバに問い合わせを行ってくれます。

## command

```yml

    command: sh -c "yarn create react-app ./my-app && \ #  react-create-appを作成
                    cd ./my-app && \ # dirに移動
                    yarn start" # package.jsonで指定されたserverの起動
```

上記設定で、dockerコンテナを作成した後、コマンド実行が自動実行されます。
`yarn start` で react-appのビルトインサーバを起動します。

`ui/my-app/package.json` に設定があるので見てみましょう。

```js
$ cat ui/my-app/package.json | grep -A 5 script
{
  ...
  "scripts": {
    "start": "react-scripts start", // これでサーバ起動する
    "build": "react-scripts build,
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
  ...
}
```

# コンテナの起動と同時にreact-create-appのサーバをワンコマンドで実行する

```sh

$ docker-compose up --build -d ui
```

`docker-compose up` で `ui` サービスを立ち上げます。


`http://localhost:3000` にアクセスするとreact appの画面が見れると思います 👏