Windows環境においてVirtualBox+Vagrant+DockerでReact開発環境を作る

ちょっとReactを触ってみようと思って。

## 対象外
- Docker for Windows (Windows 10 Homeで使えなかったため)
- Docker Toolbox (ダウンロードしようとすると公式にLegacy desktop solutionと書いてあって悲しかったので)

## 対象となる環境
- node 10.11
- Docker 18.06.1-ce
- docker-compose 1.22.0
- CentOS 7.5.1804
- VirtualBox 5.2.18
- Vagrant 2.1.5
- Windows 10 Home v.1803 build 17134.285

## VirtualBox,Vagrantのインストール
VirtualBox[こちらの](https://www.virtualbox.org/wiki/Downloads)Windows hostsから、Vagrantは[こちら](https://www.vagrantup.com/)から。

## 仮想環境作成
```terminal:cmd
# なにかディレクトリを作ります、名前はなんでも良いです
D:\>mkdir sample_pj & cd sample_pj 

# Vagrantファイルを作ります
D:\sample_pj>vagrant init

A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
```

## Vagrantfile修正
`vagrant init`したディレクトリにVagrantfileが作成されているので修正しましょう。

### config.vm.box
https://app.vagrantup.com/boxes/search
でゲストOSで選択できるboxが並んでいるので、好きなものを選びましょう。
今回は無難にCentOSを使います。

```config:Vagrantfile
config.vm.box = "centos/7"
```

### config.vm.network
ホストOS、ゲストOS間でポートフォワーディングを行うよう設定します。

```config:Vagrantfile
config.vm.network "forwarded_port", guest: 3000, host: 3000
```

### config.vm.synced_folder
ローカル(ホストOS)のディレクトリを仮想環境側へマウントする事が出来ます。ディレクトリの名前はお好みで大丈夫です。

```config:Vagrantfile
config.vm.synced_folder "./", "/mnt"
```

### config.vm.provider
synced_folderにはシンボリックリンクを貼れないという制限があり、このままだとnpmインストールでエラーが出たり、困った事になります。以下を追記しましょう。

```config:Vagrantfile
config.vm.provider "virtualbox" do |v|
  v.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate//mnt", "1"]
end
```

### config.vm.provision
docker使うためのプロビジョニングをしたいので、追加しましょう。

```config:Vagrantfile
# provisioning
config.vm.provision :shell, :path => "provision.sh"
```

## provision.sh
主にdocker, docker-composeのインストールをします。
Vagrantfileと同じ階層に`provision.sh`を作成して、以下の内容で保存してください。

```shell:provision.sh
# docker
sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

sudo yum-config-manager \
  --add-repo \
  https://download.docker.com/linux/centos/docker-ce.repo

sudo yum install -y docker-ce
sudo systemctl start docker
sudo systemctl enable docker
sudo groupadd docker
sudo gpasswd -a vagrant docker
sudo systemctl restart docker

# docker-compose
sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` -o /usr/bin/docker-compose
sudo chmod +x /usr/bin/docker-compose
```

## 仮想環境起動
コマンドプロンプトを**<font color="red">管理者として実行</font>**を選んで開き直し、 `vagrant up` して仮想環境を起動します。
(管理者として実行しなかった場合、先ほど設定した共有ディレクトリにシンボリックを貼るための設定が有効に出来ません。なのでいろいろと失敗してしまいます)

```terminal:cmd
# 起動
D:\sample_pj>vagrant up

# SSH
D:\sample_pj>vagrant ssh
```

## Dockerfile, docker-compose.yml作成
```bash:bash
# マウントしているディレクトリで
[vagrant@localhost ~]$ cd /mnt
[vagrant@localhost mnt]$ vi Dockerfile
```

Dockerfileは以下で保存してください。

```config:Dockerfile
FROM node:10.11-alpine

# create-react-app (https://github.com/facebook/create-react-app) を利用します
RUN npm install -g create-react-app

WORKDIR /var/www
```

次にdocker-compose.ymlです。

```bash:bash
[vagrant@localhost mnt]$ vi docker-compose.yml
```

以下で保存します。

```yaml:docker-compose.yml
version: '3'
services:
  creator:
    build:
      ./
    volumes:
      - ./:/var/www

  app:
    build:
      ./
    volumes:
      - ./app:/var/www
    ports:
      - 3000:3000
    environment:
      - CHOKIDAR_USEPOLLING=true
    command:
      npm start
```

## コンテナのビルド
```bash:bash
[vagrant@localhost mnt]$ docker-compose build
```

## アプリの雛形作成
雛形を作成します。

```bash:bash
[vagrant@localhost mnt]$ docker-compose run --rm creator create-react-app app
```

## アプリ実行
`--service-ports` の指定を忘れないようにしましょう。

```bash:bash
[vagrant@localhost mnt]$ docker-compose run --rm --service-ports app

Compiled successfully!

You can now view sample_app in the browser.

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

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

## ブラウザから
http://localhost:3000/ を開きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/25416/9fb4af02-f1d0-51c3-a69b-e2903607914f.png)

### src/App.js
てきとうに修正して保存してみましょう。ブラウザがリロードされ、修正点が即時に反映されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/25416/7ea3f146-dede-e320-200e-3fd330647eed.png)