【2021年】React / TypeScript使用のためのDocker + Vagrant環境を構築する

## 目的

下記の技術を使ったフロントのコンポーネントの作成を行うための環境構築を行いました。

- React
- TypeScript

目的は上記の利用ですが、本記事としてはReact/TypeScriptを触れることはありませんので、Node.jsを利用する環境の構築には利用が可能かと思います。

DockerだけでなくVagrantを採用している理由としては、自分の開発環境がmacであり、
参考記事に記載の理由で動作が遅いことを解消するためです。

## 参考記事

[DXを大幅に低下させるDocker for Macを捨ててMac最速のDocker環境を手に入れる](https://qiita.com/yuki_ycino/items/cb21cf91a39ddd61f484)


## 前準備/筆者の環境

参考記事に記載のVagrantやMutagenのインストールが必要です。
筆者の環境としては下記となります。

- MacOS 11.1
- Vagrant 2.2.7
- Mutagen 0.11.8

## 作成するもの

下記の4つのファイルを作成します。
それぞれのファイルは同一のディレクトリの配置でOKです。

- Vagrantfile
- mutagen.yml
- Dockerfile
- docker-compose.yml

起動をする際にはvagrantから立ち上げて、仮想マシンの中にsshしてdockerの立ち上げとなります。

## Vagrantfile
作成する仮想マシンの構成の記載がされているファイルです。

```bash
Vagrant.configure('2') do |config|
  config.vm.box = 'ubuntu/focal64'

  config.vm.hostname = 'frontcomponent'

  config.vm.network :private_network, ip: '192.168.60.10'
  config.vm.network 'forwarded_port', guest: 8000, host: 8000

  config.vm.provider :virtualbox do |vb|
    vb.gui = false
    vb.cpus = 2
    vb.memory = 4096
    vb.customize ['modifyvm', :id, '--natdnsproxy1', 'off']
    vb.customize ['modifyvm', :id, '--natdnshostresolver1', 'off']
  end

  config.disksize.size = '15GB'
  config.mutagen.orchestrate = true

  config.vm.synced_folder './', '/home/vagrant/front_component', type: "rsync",
    rsync_auto: true,
    rsync__exclude: ['.git/', 'log/', 'tmp/']

  config.vm.provision 'shell', inline: <<-SHELL
    echo "fs.inotify.max_user_watches = 65536" >> /etc/sysctl.conf && sysctl -p

    curl -fsSL https://get.docker.com -o get-docker.sh
    sh get-docker.sh
    usermod -aG docker vagrant

    # dockerを更新する場合にはverを調整すること
    curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    chmod +x /usr/local/bin/docker-compose
  SHELL
end
```

portの設定は今後に自分が利用する環境に合わせて設定しています。
あと、`vm.provider`などスペックの設定に関しては利用しているPCなどでチューニングすると良いかと思います。


他には自分がこれまでにハマったポイントや参考記事を拝見した後に追加した点としては下記となります。利用する場合には注意してください。

### hostname
"_"の利用ができないようです。
サービス名などを入れた場合に間違えやすいので注意が必要です。

### fs.inotify.max_user_watches
node_modulesなど外部のファイルを引いてくるディレクトリが存在する場合にファイル数が多くなりすぎて、エラーとなることがあります。その場合にはファイルのマウントから除外する方が正しいかとは思いますが、typescriptの方定義ファイルなどローカル上にマウントされてないとコード編集時にnode_modules内の型定義ファイルが見つからず加えました。  
良い知見をお持ちの方がいたら意見を伺いたいです

## mutagen.yml

```yml
sync:
  app:
    mode: "two-way-resolved"
    alpha: "./"
    beta: "frontcomponent:/home/vagrant/front_component"
    ignore:
      vcs: true
      paths:
        - "/log"
        - "/tmp"
```

vagrantとのファイル同期にmutagenを利用します。
詳細に関しては記事にまとめるほどには理解が追いついていませんので、参考記事を参照していただけると良いかと思います。


## Dockerfile
[Docker Hub](https://hub.docker.com)に置いてあるDockerのイメージファイルをベースとして、
今回利用するコンテナのベースイメージを作成します。


```shell
FROM node:15.5.1

ENV LANG C.UTF-8
ENV WORKSPACE=/var/www/front_component/

RUN curl -sL https://deb.nodesource.com/setup_15.x | bash - 
RUN apt install -y less build-essential nodejs
RUN apt install -y vim less
RUN npm install n -g
RUN n 14.15.4

WORKDIR $WORKSPACE
```

Docker Hubに置いてあるイメージを元に、今回の環境構築用のベースイメージを作成します。  
今回は、今後にreact/typescriptを入れていくことを想定しているのでnodeのイメージをして、npmのインストールをしています。

## docker-compose.yml

```yml

version: '3.7'

services:
  front:
    build: .
    image: front:1.0
    container_name: front
    tty: true
    stdin_open: true
    ports:
      - "8000:8000"
    environment: {}
    volumes:
      - .:/var/www/front_component
    # command: "bash -c 'npm i && npm run watch'"
```

コンテナ作成用の設定になります。
コメントアウト部分は今後にreact/typescriptを入れた後に利用する想定ですが、
ここまでの環境構築では利用をしないのでコメントアウトとしています。


## vagrantおよびdockerの立ち上げ

### 立ち上げ方
```shell
# 先にcdコマンドで上記で作成したファイルの置いてあるディレクトリに移動する

vagrant up  # vagrantの立ち上げ
vagrant ssh # vagrant内へsshでアクセス
cd front_component   # vagrantにローカルのファイルをマウントしているディレクトリに移動
docker-compose up -d # dockerの立ち上げ
```

以上で環境の立ち上げ完了です。

上記のコマンドと合わせて、自分がよく使うコマンドを記載しておきます。
簡易的な説明のみなので、ちゃんと使う場合には調べて使ってください

#### vagrant系

```shell
vagrant up      # vagrantの立ち上げ
vagrant ssh     # 立ち上げたvagrantにsshアクセスする
vagrant halt    # vagrantの終了
vagrant destroy # vagrantで作成した仮装イメージごと削除
```

#### docker系
```shell
docker ps # 起動中のdockerのimageを確認する
docker exec -ti <コンテナ名> /bin/bash # コンテナの中にssh的にアクセスする
docker attach <コンテナ名> # コンテナで起動中のプロセスを表示する
docker logs <コンテナ名>   # 強制終了したコンテナの終了時のログなどを見るのに利用する
```

---
初投稿ε('∞'*)ﾌｩｰ