DockerでReactの環境を作成してみた

# はじめに
この記事ではJavaScriptのライブラリであるReactの環境をDockerを使用して構築したいと思います。

## 目次
1. Dockerfileの用意
2. Dockerfileをビルド
3. コンテナの起動
4. Reactアプリケーションの作成
5. Reactアプリケーションの起動
6. ブラウザで確認
7. まとめ

## 1. Dockerfileの用意

今回はcreate-react-appを使用してReactの環境を構築していきます。
ディレクトリ構成は以下です。

```bash:ディレクトリ構成
.
├── app         # Reactアプリケーションのフォルダ
└── Dockerfile  # React環境のDockerfile
```
```Dockerfile:Dockerfile
# nodeのverを指定してDockerのイメージをpull
FROM node:13.5.0

# Reactアプリケーション作成時に最低限の環境を提供してくれるライブラリをインストール
RUN yarn global add create-react-app

# コンテナ接続時のディレクトリを指定
WORKDIR /home

# アプリケーションの起動時にコンテナで開放するポートを指定
EXPOSE 3000
```

## 2. Dockerfileをビルド

DockerfileからDockerイメージを作成します。
イメージ名は`react-tutorial`にします。
以下のコマンドをDockerfileが存在するディレクトリで実行してください。

```bash:Dockerイメージのビルド
$ docker build --rm -f "react-tutorial/Dockerfile" -t react-tutorial:latest "react-tutorial"
```

## 3. コンテナの起動

起動すると以下のようになると思います。
これで、Reactアプリケーションが作成できる環境のコンテナに接続できたことになります。

```bash:Dockerコンテナの起動
$ docker run --rm -it -v ${PWD}/app:/home/react-tutorial  -p 3000:3000/tcp react-tutorial:latest /bin/bash
root@03887209ce2d:/home# 
```

## 4. Reactアプリケーションの作成
それでは、Reactアプリケーションの作成をしてきます。
作成には`create-react-app`を使用します。

```bash:Reactアプリケーションの作成
root@03887209ce2d:/home# create-react-app react-tutorial
```

<details><summary>コマンド実行中の表示（長いので畳んでおきます）</summary><div>

```
Creating a new React app in /home/react-tutorial.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts with cra-template...

yarn add v1.21.1
[1/4] Resolving packages...
[2/4] Fetching packages...
warning sha.js@2.4.11: Invalid bin entry for "sha.js" (in "sha.js").
info fsevents@1.2.9: The platform "linux" is incompatible with this module.
info "fsevents@1.2.9" is an optional dependency and failed compatibility check. Excluding it from installation.
info fsevents@2.1.2: The platform "linux" is incompatible with this module.
info "fsevents@2.1.2" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning "react-scripts > @typescript-eslint/eslint-plugin > tsutils@3.17.1" has unmet peer dependency "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta".
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 35 new dependencies.
info Direct dependencies
├─ cra-template@1.0.0
├─ react-dom@16.12.0
├─ react-scripts@3.3.0
└─ react@16.12.0
info All dependencies
├─ @babel/plugin-proposal-class-properties@7.7.4
├─ @babel/plugin-proposal-decorators@7.7.4
├─ @babel/plugin-proposal-nullish-coalescing-operator@7.7.4
├─ @babel/plugin-proposal-numeric-separator@7.7.4
├─ @babel/plugin-proposal-optional-chaining@7.7.4
├─ @babel/plugin-syntax-decorators@7.7.4
├─ @babel/plugin-syntax-flow@7.7.4
├─ @babel/plugin-syntax-nullish-coalescing-operator@7.7.4
├─ @babel/plugin-syntax-numeric-separator@7.7.4
├─ @babel/plugin-syntax-optional-chaining@7.7.4
├─ @babel/plugin-transform-flow-strip-types@7.7.4
├─ @babel/plugin-transform-runtime@7.7.4
├─ @babel/plugin-transform-typescript@7.7.4
├─ @babel/preset-typescript@7.7.4
├─ @types/parse-json@4.0.0
├─ babel-plugin-macros@2.7.1
├─ babel-plugin-named-asset-import@0.3.5
├─ babel-preset-react-app@9.1.0
├─ core-js@3.6.1
├─ cra-template@1.0.0
├─ eslint-config-react-app@5.1.0
├─ fork-ts-checker-webpack-plugin@3.1.0
├─ lines-and-columns@1.1.6
├─ open@7.0.0
├─ promise@8.0.3
├─ raf@3.4.1
├─ react-app-polyfill@1.0.5
├─ react-dev-utils@10.0.0
├─ react-dom@16.12.0
├─ react-error-overlay@6.0.4
├─ react-scripts@3.3.0
├─ react@16.12.0
├─ scheduler@0.18.0
├─ whatwg-fetch@3.0.0
└─ yaml@1.7.2
Done in 36.57s.

Installing template dependencies using yarnpkg...
yarn add v1.21.1
[1/4] Resolving packages...
[2/4] Fetching packages...
info fsevents@2.1.2: The platform "linux" is incompatible with this module.
info "fsevents@2.1.2" is an optional dependency and failed compatibility check. Excluding it from installation.
info fsevents@1.2.9: The platform "linux" is incompatible with this module.
info "fsevents@1.2.9" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning "react-scripts > @typescript-eslint/eslint-plugin > tsutils@3.17.1" has unmet peer dependency "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta".
warning " > @testing-library/user-event@7.2.1" has unmet peer dependency "@testing-library/dom@>=5".
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 18 new dependencies.
info Direct dependencies
├─ @testing-library/jest-dom@4.2.4
├─ @testing-library/react@9.4.0
├─ @testing-library/user-event@7.2.1
├─ react-dom@16.12.0
└─ react@16.12.0
info All dependencies
├─ @sheerun/mutationobserver-shim@0.3.2
├─ @testing-library/dom@6.11.0
├─ @testing-library/jest-dom@4.2.4
├─ @testing-library/react@9.4.0
├─ @testing-library/user-event@7.2.1
├─ @types/prop-types@15.7.3
├─ @types/react-dom@16.9.4
├─ @types/react@16.9.17
├─ @types/testing-library__dom@6.11.0
├─ @types/testing-library__react@9.1.2
├─ css.escape@1.5.1
├─ csstype@2.6.8
├─ min-indent@1.0.0
├─ react-dom@16.12.0
├─ react@16.12.0
├─ redent@3.0.0
├─ strip-indent@3.0.0
└─ wait-for-expect@3.0.1
Done in 9.58s.
Removing template package using yarnpkg...

yarn remove v1.21.1
[1/2] Removing module cra-template...
[2/2] Regenerating lockfile and installing missing dependencies...
info fsevents@2.1.2: The platform "linux" is incompatible with this module.
info "fsevents@2.1.2" is an optional dependency and failed compatibility check. Excluding it from installation.
info fsevents@1.2.9: The platform "linux" is incompatible with this module.
info "fsevents@1.2.9" is an optional dependency and failed compatibility check. Excluding it from installation.
warning " > @testing-library/user-event@7.2.1" has unmet peer dependency "@testing-library/dom@>=5".
warning "react-scripts > @typescript-eslint/eslint-plugin > tsutils@3.17.1" has unmet peer dependency "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta".
success Uninstalled packages.
Done in 7.62s.

Success! Created react-tutorial at /home/react-tutorial
Inside that directory, you can run several commands:

  yarn start
    Starts the development server.

  yarn build
    Bundles the app into static files for production.

  yarn test
    Starts the test runner.

  yarn eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd react-tutorial
  yarn start

Happy hacking!
```

</div></details>

## 5. Reactアプリケーションの起動
Reactアプリケーションが作成されたので、実際に起動します。

```bash:Reactアプリケーションの起動
# ディレクトリ確認
root@03887209ce2d:/home# ls
node  react-tutorial
root@03887209ce2d:/home# cd react-tutorial/
# Reactアプリケーションの起動
root@03887209ce2d:/home/react-tutorial# yarn start
```

## 6. ブラウザで確認

`yarn start`を実行すると以下のように出力されます。

```bash:Reactアプリケーションの起動後
Compiled successfully!

You can now view react-tutorial in the browser.

  Local:            http://localhost:3000/
  On Your Network:  http://172.17.0.3:3000/

Note that the development build is not optimized.
To create a production build, use yarn build.
```

あとは、ブラウザから`http://localhost:3000/`にアクセスしてみましょう。
以下のような表示がされれば完了です。
<img width="1919" alt="スクリーンショット 2020-01-01 3.36.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190554/2ed0faea-668b-790a-6cad-8197930a5fb6.png">

## 7. まとめ
Dockerを使用してReactの環境をお手軽に作成できました。
ホストマシンの環境をいじらずにお試しで環境を構築できるのはめっちゃ便利ですよね！！
あとは、appフォルダ配下のファイルを編集してアプリケーションを作成していくのみです！！
指摘や質問があれば大歓迎なので、是非よろしくお願いします。
以上です。ありがとうございました！