Docker for MacをやめてUbuntu + VagrantでDocker開発環境を構築する方法

#はじめに
Docker for Macを使ってチーム開発を行っていたんですが、遅いのでDocker for Macをやめて仮想環境を立ち上げて爆速のDocker環境を作ろう！！と至りました。
###Docker for Macが遅い理由
Linux上ではホストとコンテナ間で VFS を基盤に共有しているので、オーバーヘッドのない反映を保証します。しかしながら、 macOS （および他の Linux 以外のプラットフォーム）では、完全な一貫性を保つために著しいオーバーヘッドがあります、、、、、、
[Docker日本語ドキュメント](https://docs.docker.jp/docker-for-mac/osxfs-caching.html)や他の方のQiitaの記事でもそう書かれていましたがあんまりわからない、、、
とりあえず、Docker for Macのファイル共有システムの[osxfs](https://docs.docker.jp/docker-for-mac/osxfs.html)に対するマウントが遅いっぽい、
`OSXのFSEvents API`と`Linux’s inotify API`をマッピングさせてたりするのが主な原因なんですね
[遅い原因](https://forums.docker.com/t/file-access-in-mounted-volumes-extremely-slow-cpu-bound/8076/158)

**Docker for Macと今回構築する環境（Virtual Box + Docker)との違い**は
[DXを大幅に低下させるDocker for Macを捨ててMac最速のDocker環境を手に入れる](https://qiita.com/yuki_ycino/items/cb21cf91a39ddd61f484)
上記の方の記事がものすごくわかりやすかったです！！図が助かるー( ；∀；)
#動作環境
####PCスペック
Mac OS Catalina 10.15.7
####Docker バージョン
20.10.0-beta1
####Vagarnt バージョン
Vagrant 2.2.13
####Ubuntu バージョン
Ubuntu 18.04.5 LTS
###補足
今回、誤ってubuntu16.04LTSから18.04LTSへバージョンアップしてしまったためVagrant Box（OS)をbionic64にしています。
本来ならばxenial64です。（Ubuntu16.04の場合）
Ubutnuのコードネームに関してまとめてくれている記事が下記です。
[ubuntu コードネーム](https://qiita.com/obukoh/items/cac8007bfe3ede816531)

ただ、**bionic64のところをxenial64に変えていくだけで大丈夫です⭕**

#概要
####①VirtualBoxとVagrantをインストールする
####②Dockerとmutagen(後述)用のvagrantプラグインをインストール
####③vagrantファイルの作成
####④mutagenでファイル同期する
####⑤Dockerを起動する
手順が多く見えますが頑張っていきましょう、、、（笑）
##①VirtualBoxとVagrantをインストールする
Homebrewを使用して、必要なツールをインストールしていきます。
[Homebrewインストール](https://brew.sh/)
#####VirtualBoxをインストール

```
brew cask install virtualbox
```
#####Vagrantをインストール

```
brew cask install vagrant
```
#####Vagrant Boxをダウンロード
Vagrant Box（OS)をダウンロードしていきます。（結構時間かかりました）
`ubuntu/bionic64`を選んだ理由は下記
`Ubuntu18.04`の中でもメジャーのほうがいいのかなと選ばせていただきました
[Ubuntu 18.04のVagrant box比較](https://alpha3166.github.io/blog/20200504.html)

```
vagrant box add ubuntu/bionic64 
```
ダウンロード完了後以下のコマンドで確認できます

```
vagrant box list
```
```
ubuntu/bionic64 (virtualbox, 20200229.0.0)
```
##②Dockerとmutagen(後述)用のvagrantプラグインをインストール
必要となるVagrant Pluginをインストールします。
`mutagen`については後ほど説明します。

```
vagrant plugin install vagrant-disksize vagrant-hostsupdater vagrant-mutagen vagrant-docker-compose
```
##③vagrantファイルの作成
開発ディレクトリに`vagrant init`

```
cd ~/my_app       (開発ディレクトリに移動）
vagrant init ubuntu/bionic64      (vagrantで初期化)
```
以下の文が出てくるので`vagrantfile`ができてます！

```
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ファイルの内容は以下のように編集してください！
`config.vm.hostname` は 開発ディレクトリでOKだよー！
その他よくわからなかったら
[VagrantコマンドとVagrantfileの設定メモ](https://qiita.com/pugiemonn/items/bcd95a35c3ec7624cd61)
上記の方の記事の「vagrantfileの設定」を見るとわかりやすかったです。ありがとうございます(:_;)

```:~/my_app/Vagrantfile
Vagrant.configure('2') do |config|
  config.vm.box = 'ubuntu/bionic64'

  config.vm.hostname = 'my_app'

  config.vm.network :private_network, ip: '192.168.50.10'
  
  config.vm.network "forwarded_port", guest: 80, host: 8080

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

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

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

  config.vm.provision :docker, run: 'always'
  config.vm.provision :docker_compose
end
```
config.vm.synced_folderのホスト側のパスは、`"./"`のようにしてしまうと作業をシェアする際に、作業環境ごとにパスを書き換える必要がないので楽になります。

以上で、Vagrant+VirtualBoxの準備は完了です。
##④mutagenでファイル同期する
編集したファイルをMacとLinuxで同期させます。[Mutagen](https://mutagen.io/)というツールで実現します。
以下のコマンドで、mutagenをインストールします。(これも時間かかりました）

```
brew install mutagen-io/mutagen/mutagen
```
インストール後、mutagenの設定ファイルmutagen.ymlを作成します。作成する場所は、**Vagrantfileと同じディレクトリ**にしてください。

```:~/my_app
touch mutagen.yml
```
内容は以下のようになります。

```yaml:~/my_app/mutagen.yml
sync:
  app:
    mode: "two-way-resolved"
    alpha: "./"
    beta: "my-app:/home/vagrant/app"
    ignore:
      vcs: true
      paths:
        - "/node_modules"
        - "/log"
        - "/tmp"
```
その後 $ vagrant up でVMを起動すると、Mutagenによって双方向のファイル同期が行われます。
この同期は双方向にほぼリアルタイムで行われ、ファイルシステムのマウントではなくファイルの転送で実現されているため、最終的にDockerコンテナへマウントされた際のオーバーヘッドはほぼ発生しません。
##⑤Dockerを起動する
####Vagrantを起動
コマンド実行後に、エラーが発生しました,,,,,

```:~my_app
vagrant up
/Users/hoge/.vagrant.d/gems/2.4.9/gems/vagrant-mutagen-0.1.2/lib/vagrant-mutagen/Mutagen.rb:22:in `initialize': No such file or directory @ rb_sysopen - /Users/hoge/.ssh/config (Errno::ENOENT)
```
`config`がないよって言ってますね（汗）
作ってあげましょう！！

```:~my_app
touch /Users/hoge/.ssh/config
```
もう一度！！

```:~my_app
vagrant up
```
今度はうまくできたみたいですε-(´∀｀*)ﾎｯ
####仮想環境にSSH接続

```
vagrant ssh
```
すると今度はなんかupdateの案内が、、

```
New release ''20.04.1 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
```
これに関してはしないほうがいいかもですね。

`vagrant box add ubuntu/bionic64`
でしっかりバージョンに合わせたOSをダウンロードする必要があるっぽいので、、



####Vagrantの中で、Dockerを起動
以下のコマンドは、プロジェクトディレクトリにdocker-compose.ymlが存在している場合の例です。

```
cd app
docker-compose up
```
###参考文献
>VirtualBoxとVagrantでUbuntuの仮想環境を構築してSSH接続するまで
>>https://temlog.net/ubuntu-vagrant/

>vagrant+docker-compose環境を構築
>>https://qiita.com/maro_amoeba/items/740c9e84abaf89fc625f