Vagrantを使う「Mac最速のDocker環境」を初心者向けに解説【遅いMac for Dockerを卒業】

:::note warn
Docker for Mac の改善により、現在（2023/11/24）はマウント等含め、かなり早くなっております。
相当な理由がある場合にのみ、試すとよいかと思います。
:::

下記の記事を参考にVB上にDocker環境を構築してみたのですが、いくつか調べて対応しなければいけなく、初心者にとってはとっつきにくいかと思いました。

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

初心者向けで細かくコマンドを解説していきたいと思います。

<font color="FireBrick">2020年4月2日追記: docker-composeのInstallをプラグインに変更しました。</font>

<font color="FireBrick">2020年5月6日追記: mutagenのセッションリセット方法を追記しました。</font>

## はじめに

### 前提
* Homebrew導入済み
* Dockerの使い方がわかる

### 対象者

* Mac for Dockerを使っている人
* Docker上で開発をしていて、重いなって感じてる人

### 大まかな流れ

1. VirtualBoxをインストール
2. Vagrantをインストール
3. Vagrantの設定ファイル作成
4. Mutagenのインストール・セットアップ
5. VagrantにSSH接続してDocker起動

## 導入方法

### VirtualBoxをインストール

[VirtualBox](https://www.virtualbox.org/)をbrew caskを使ってインストールします。

```bash:
brew install --cask virtualbox
```

インストール開始時にパスワード入力を求められるので、パスワードの入力をします。

### Vagrantをインストール

[Vagrant](https://www.vagrantup.com/)をインストールします。

```bash:
brew install --cask vagrant
```

パスワード入力を求められるのでパスワードの入力をします。

### Vagrant Boxをダウンロード

続いては、ボックスを追加します。(ダウンロードされるので時間がかかります）

ボックスがいわゆるOSの部分になります。ダウンロードに結構時間がかかります。

```bash:
vagrant box add ubuntu/xenial64
```

ダウンロードが完了したら`vagrant box list`で確認します。

```bash:
vagrant box list
```

```
ubuntu/xenial64 (virtualbox, 20210119.0.0)
```

### Vagrant Pluginをインストール

必要となるVagrant Pluginをインストールします。

```bash:
vagrant plugin install vagrant-disksize vagrant-hostsupdater vagrant-mutagen vagrant-docker-compose
```

### Vagrantのセットアップ
開発ディレクトリに移動します。

例

```bash:
cd ~/my_app
```

`vagrant init`で環境ファイルを作成します。

```bash:~/my_app
vagrant init ubuntu/xenial64
```

作成された`Vagrantfile`を編集していきます。

中身を下記の内容に書き換えてください。

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

  config.vm.hostname = 'my-app'

  config.vm.network :private_network, ip: '192.168.50.10'

  config.vm.provider :virtualbox do |vb|
    vb.gui = false
    vb.cpus = 4
    vb.memory = 4096
    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/']

  config.vm.provision :docker, run: 'always'
  config.vm.provision :docker_compose
end
```

必要に応じて調整してください。
ご自身のスペック以上を設定するとフリーズするようです。

`config.vm.hostname = 'my-app'` 任意のホストネーム
`vb.cpus = 4` CPUコア数
`vb.memory = 4096` メモリサイズ
`config.disksize.size = '30GB'` ディスクサイズ

### Mutagenのインストール・セットアップ

続いて、ファイル同期ソフトの[Mutagen](https://mutagen.io/)をインストールします。

```bash:
brew install mutagen-io/mutagen/mutagen
```

その後、`Vagrantfile`と同じ階層に`mutagen.yml`作成します。

```bash:~/my_app
touch mutagen.yml
vim mutagen.yml
```

```yml:~/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"
```
`beta: "my-app:/home/vagrant/app"` の`my-app`は
`Vagrantfile`で設定したhostnameと一致させてください。

### Vagrantを起動

Vagrantを起動します。

```bash:~/my_app
vagrant up
```

VirtualBoxを初めて入れた方は、このタイミングで「セキュリティとプライバシー」で弾かれるので、下記記事を参考に`ダウンロードしたアプリケーションの許可`を許可して、再度`vagrant up`します。

[インターネットからダウンロードしたアプリの実行許可](https://pc-karuma.net/download-app-security/)

初回起動時はDockerとDocker Composeがインストールされるので時間がかかります。

<font color="FireBrick">sshのconfigファイルを作成していないと、このタイミングでエラーが出るようです。</font>

下記の記事にて対処法を解説くださったので、エラーの方は参考にしてみてください。

[`initialize': No such file or directory エラーの対処法](https://qiita.com/mightysosuke/items/6004d3aaf3411601be22)

また、下記のようなエラーが出た場合は、こちらの記事を参考に対処してみてください。

https://qiita.com/atu4403/items/a408645412a0cbd6a465

```
The provider for this Vagrant-managed machine is reporting that it
is not yet ready for SSH. Depending on your provider this can carry
different meanings. Make sure your machine is created and running and
try again. Additionally, check the output of `vagrant status` to verify
that the machine is in the state that you expect. If you continue to
get this error message, please view the documentation for the provider
you're using.
```

### 仮想環境にSSH接続

`vagrant up`が完了したらSSH接続します。

```bash:~/my_app
vagrant ssh
```

`Welcome to Ubuntu 16.04.6 LTS`と出ていたらSSH接続完了です。

```bash:~/my_app
vagrant ssh
```

```:vagrant
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-174-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

 * Latest Kubernetes 1.18 beta is now available for your laptop, NUC, cloud
   instance or Raspberry Pi, with automatic updates to the final GA release.

     sudo snap install microk8s --channel=1.18/beta --classic

 * Multipass 1.1 adds proxy support for developers behind enterprise
   firewalls. Rapid prototyping for cloud operations just got easier.

     https://multipass.run/

1 package can be updated.
1 update is a security update.

New release '18.04.4 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
```

アプリケーションディレクトリに移動してdocker-composeを起動してみましょう！

```bash:~/
cd app
docker-compose up
```

立ち上がったアプリケーションにはVagrantfileで指定したIPアドレスでアクセスできます。

`http://192.168.50.10:3000/`

それでは快適Dockerライフをお楽しみください！

### Vagrantの終了方法

`vagrant halt`にてVMを終了します。

```bash:~/my_app
vagrant halt
```

`vagrant status`にて終了できたか確認できます。

`poweroff`になっていれば終了しています。
`running`になっていれば`vagrant halt`にて終了してください。

```bash:~/my_app
vagrant status
=> Current machine states:

default        poweroff (virtualbox)
```

`vagrant halt`を行わずにVMを終了した場合にはセッションが削除されずに残ってしまうという問題があるそうです。

そのまま再度起動すると、mutagenが多重にセッションを貼りバグの原因になるそうなので、`mutagen sync list`で不要なセッションがないか確認してください。

```bash:~/my_app
 mutagen sync list
=>
--------------------------
No sessions found
--------------------------
```

もし`No sessions found`ではなく、セッションが表示される場合はデーモンを再起動するとセッションがリセットされます。

```bash
mutagen daemon stop
mutagen daemon start
```

再度`mutagen sync list`を行いセッションがなくなっているか確認してください。

## 結果
rails consoleの初回起動が42秒短縮されました。
`Docker for Mac: 46秒
VM on Docker: 4秒`

```ruby:
time rails c
=> Loading development environment (Rails 5.2.4.1)
# Docker for Mac
real   46.693s
# VirtualBox + Docker
real    4.458s
```

```ruby:
time rubocop
=> Inspecting 92 files
# Docker for Mac
real   58.52s
# VirtualBox + Docker
real    5.54s
```

```ruby:
time rspec
=> 54 examples, 0 failures
# Docker for Mac
real   12.28s
# VirtualBox + Docker
real    5.91s
```

Dockerの初回起動も早くなり、軽快に開発が進められるようになりました！

## まとめ
VirtualBoxやVagrantを初めて触ったので仮想環境について勉強になりました。

私自身はDockerでの開発を始めたばかりで、そもそもDocker for Mac以外を使ったことがなかったので、そういうもんだとばかり思っていました。

参考にさせて頂いた記事を見つけ、実際に試してみてとてもよかったです。

とてもためになったので、なぜVM環境に載せたのか、など下記記事をチェックしてみてください！

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