Docker for Mac が遅いので VagrantでUbuntu環境を立てる

＃前提条件
OS: MacOS 14.15(Catalina)
Homebrew導入済み
Docker for Macを使っていてsyncが遅い場合

#はじめに
Docker Desktop for Macは以下のような理由でホストPCとコンテナとのファイル同期が遅いようです。

>ボトルネックはマウントしているボリュームに対する読み書きの同期です。
通常、開発時にはMacOS(ホスト)のソースコードが保存されたディレクトリを、volume引数でdockerコンテナへマウントします。
>
>dockerはマウントされたホスト側のディレクトリとコンテナを同期し、完全な一貫性を保証します。
>その際、ファイルシステムがMacOSはosxfsのため、オーバーヘッドが発生して遅くなります。
>
>仮にホストがLinuxOSでdockerコンテナにマウントしている場合は、共にファイルシステムはVFSのため直接共有されるのでオーバーヘッドは生じません。
>ホストがWindowsOSの場合も同様にオーバーヘッドが生じますが、MacOSほど目に見えて遅くならないため、許容範囲内と思われます。
>
>　[MacのDockerが遅い原因と対処方法（公式）](https://wonwon-eater.com/mac-docker-performance/)

- その他
    - [Docker x Laravel めちゃくちゃ遅い Docker for Mac を爆速化する](https://qiita.com/ucan-lab/items/a88e2e5c2a79f2426163#docker-for-mac-%E9%81%85%E3%81%84%E5%8E%9F%E5%9B%A0)
    - [Docker For Macが遅い](https://qiita.com/FattyRabbit/items/b81575ed9d2f463fa619#%E9%81%85%E3%81%84%E7%90%86%E7%94%B1)

既知の問題のようです。

#実際の作業

##VirtualBoxをインストール

```zsh
$brew --cask install virtualbox
```

###VirtualBoxとは?
>  VirtualBox is a powerful x86 and AMD64/Intel64 virtualization product for enterprise as well as home use. Not only is VirtualBox an extremely feature rich, high performance product for enterprise customers, it is also the only professional solution that is freely available as Open Source Software under the terms of the GNU General Public License (GPL) version 2. See "About VirtualBox" for an introduction.
>
>Presently, VirtualBox runs on Windows, Linux, Macintosh, and Solaris hosts and supports a large number of guest operating systems including but not limited to Windows (NT 4.0, 2000, XP, Server 2003, Vista, Windows 7, Windows 8, Windows 10), DOS/Windows 3.x, Linux (2.4, 2.6, 3.x and 4.x), Solaris and OpenSolaris, OS/2, and OpenBSD.
> [Oracle VM VirtualBox](https://www.virtualbox.org/)

仮想環境を動かしてくれるクロスプラットフォームなアプリケーションです。

---


##Vagrantをインストール

```zsh
$brew install --cask vagrant
```

###Vagrantとは?
>Vagrant is a tool for building and managing virtual machine environments in a single workflow. With an easy-to-use workflow and focus on automation, Vagrant lowers development environment setup time, increases production parity, and makes the "works on my machine" excuse a relic of the past.
>[Introduction | Vagrant by HashiCorp](https://www.vagrantup.com/intro)

VirtualBoxとかをうまく解釈して適切に構成するワークフローを提供してくれます。
プラグイン次第でVMWare等とも連携できるようです。

---

##Vagrantをインストール

```zsh
$brew install --cask vagrant
```
 
##Vagrant Pluginをインストール
今回インストールするのは以下

- vagrant-disksize 
- vagrant-hostsupdater 
- vagrant-docker-compose

```zsh
$vagrant plugin install vagrant-disksize vagrant-hostsupdater vagrant-docker-compose
```

##VirtualBoxのイメージをダウンロード

```zsh
$vagrant box add "ubuntu/focal64"
```
vagrant boxコマンドは

- add
- list
- outdated
- prune
- remove
- repackage
- update

がある
[Vagrant box command-line Interface](https://www.vagrantup.com/docs/cli/box)
イメージを捨てたくなった場合は`$vagrant box remove NAME`と打つと削除できる。

##mutagenインストール
ファイル同期にmutagenを使うのでこれをホストPCにインストールしておく

```zsh
$brew install mutagen-io/mutagen/mutagen
```

##Vagrantで経由でVirtualBox上の仮想OSを立てる

```zsh
$cd /path/to/your_project/
```

```zsh
$vagrant init ubuntu/focal64
```
でカレントディレクトリにVagrantfileが作成される

Vagrantfileを以下のように編集

```ruby:Vagrantfile

#初期化時に実行するスクリプト
$script = <<SCRIPT
sudo apt-get update
sudo apt-get -y install git nodejs
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash
cd /home/vagrant

SCRIPT

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"

    config.vm.hostname = 'ubuntu20'
  
    config.vm.network :private_network, ip: '192.168.50.10'
    
    config.vm.provider :virtualbox do |vb|
      #Headlessモード
      vb.gui = false
      #VirtualBoxで利用するCPU
      vb.cpus = 4
      #VirtualBoxで利用するメモリー
      vb.memory = 4096
      vb.customize ['modifyvm', :id, '--natdnsproxy1', 'off']
      vb.customize ['modifyvm', :id, '--natdnshostresolver1', 'off']
    end
    #ディスクサイズ
    config.disksize.size = '40GB'
    
    #syncさせたいディレクトリ  
    config.vm.synced_folder './vm', '/home/vagrant',create: "true" ,owner: "vagrant", group: "vagrant", type: "rsync",
      rsync_auto: true,
      rsync__exclude: ['.git/', 'node_modules/', 'log/', 'tmp/']
  
    config.vm.provision "shell", inline: "echo 'start provision'"
    config.vm.provision "shell", inline: $script
    config.vm.provision "shell", inline: "echo 'finish provision'"
    config.vm.provision :docker, run: 'always'
    config.vm.provision :docker_compose
end
```

##mutagen.ymlを作成

```zsh
$touch mutagen.yml
```

下記のように編集

```yml:mutagen.yml
sync:
  defaults:
    mode: "two-way-resolved"
    ignore:
      vcs: true
      paths:
        - "node_modules/"
        - "log/"
        - "tmp/"
    symlink:
      mode: "portable"
    watch:
      mode: "portable"
  ubuntu20:
    alpha: "./vm"
    beta: "ubuntu20:/home/vagrant"
```
これらについて詳しくは[こちら](https://mutagen.io/documentation/introduction/configuration)


#Vagrant起動

```zsh
$vagrant up
```
同時に、mutagenを起動する。

```zsh
$mutagen sync create --name ubuntu20 ./vm ubuntu20:/home/vagrant
```
構文は
```mutagen sync create --name 名前 ホストPCのエンドポイント ゲストPC:ゲストPCのエンドポイント```

これで同期設定もできているはずなので、

```zsh
vagrant ssh
```
でVirtualBoxに接続する。

#Dockerを起動
`vagrant ssh`でログインした時点で`docker`コマンドが使える。

任意のディレクトリまで移動して、

```
$ docker-compose up -d --build
```
などがつかえる。

#感想

フロントエンドの開発でDocker Desktop for Macを使って立てていたときはリロードが話にならないくらい遅かったが
これなら十分使えるかなーというレベルです。
`vagrant`を経由するのでひと手間ありますがやって見る価値はあると思います。

#結果
- VirtualBox上のUbuntuでDockerが使える。
- 早い



#参考
- [Oracle VM VirtualBox](https://www.virtualbox.org/)
- [Vagrant CLI](https://www.vagrantup.com/docs/cli)
- [mutagen-io / mutagen (Github)](https://github.com/mutagen-io/mutagen)
- [MacのDockerが遅い原因と対処方法（公式）](https://wonwon-eater.com/mac-docker-performance/)
- [Docker x Laravel めちゃくちゃ遅い Docker for Mac を爆速化する](https://qiita.com/ucan-lab/items/a88e2e5c2a79f2426163#docker-for-mac-%E9%81%85%E3%81%84%E5%8E%9F%E5%9B%A0)
- [Docker For Macが遅い](https://qiita.com/FattyRabbit/items/b81575ed9d2f463fa619#%E9%81%85%E3%81%84%E7%90%86%E7%94%B1)

---

Dockerに関してはまた次回書きます。