Docker Desktop for Mac/Win (Docker for Mac/Win) が遅くて困っているあなたへ

# はじめに

Docker Desktopを使用していて動作が重い、CPU負荷が凄いことになっている、volume mountするとIOがとても遅いといった事象で困っている方は沢山いらっしゃるかと思います。

私も同じく、Docker for Macを使用していてDocker(Daemon)の立ち上がりが遅かったり、暴走してDockerのプロセスをkillしたりすることが多々ありました。

しかし、諸々の事情でDockerで開発しなければならない場合もあると思います。
そんな方は是非、こちらの記事を参考に`Vagrant on Docker`への乗り換えを検討してみてください！

# メリット

- Docker Desktop特有のVolume mount遅い問題が解決できる
- Windows 10ユーザーはProじゃなくても大丈夫
- CPU暴走しなくなる？(体感の問題かも)
- ローカルに複数のDocker Daemonを建てられる
    - Kubernetesのクラスタも作れます
- VMのイメージを他の人に渡せば開発環境ごと共有できる
- ホストOSが変わってもそのまま使える
    - PCのお引っ越しも楽々！
    - 開発ツールのインストール用shell(tigなど)を作ってしまえば開発環境も一発で構築!

# デメリット

- Linuxの知識が必要(Docker使いなら大丈夫かと思います)
- コンテナ内で生成したファイルはPermission変更が必要  
→`rails generate`や`php artisan`のようなコマンドでソースの雛形を生成する際には毎回権限付与が必要

Permissionは以下のコマンドで対応可能です。
LinuxでDocker運用している方で簡単な回避方法があれば教えていただきたいです。
(Dockerfileでadduserする方法以外)

```bash
# ホストではなく、VM上で実行(Dockerコンテナ外)
sudo chmod 777 <対象のファイル>
# または
sudo chmod -R 777 <対象のディレクトリ>
```

# 開発環境

- macOS (Windowsでも大丈夫なはず)
- VirtualBox
- Vagrant
 - Ubuntu 18.04 LTS
     - Docker
     - Docker Compose
            
※階層で仮想環境の中身を表現しています

# セットアップ

## VirtualBox/Vagrantインストール

以下、Macの場合で記載します。
Windowsの方は以下からダウンロードしてください。
https://www.vagrantup.com/downloads.html


```bash
# 前提：Homebrew, hobebrew-caskが使用できること
brew cask install virtualbox
brew cask install vagrant
```

## VMのセットアップ

私はUbuntu大好きっ子なので、Ubuntuを対象に構築します。

楽をしたい方は以下のリポジトリを`git clone`してください。
https://github.com/MasanoriIwakura/vagrant-docker.git

```bash
# Vagrantの設置を保持するディレクトリを作成
mkdir vagrant-docker
cd vagrant-docker

# Vagrantfile作成
vagrant init ubuntu/bionic64
```

## VM内にDockerをインストール

`Vagrantfile`を編集し、初期起動時に自動でDockerをインストールされるようにします。

今回は記載しませんが、vimを使用されている方はvimrcの設定、
gitの初期設定、tigのインストールなど、開発で使用するツールの設定もこのタイミングで行っておくと便利です。

```bash
# インストール用のshellを作成
touch dockerinstall.sh
```

中身はこんなかんじです。

```bash

#!/bin/bash

sudo apt update
sudo apt -y install \
        apt-transport-https \
        ca-certificates \
        curl \
        gnupg-agent \
        software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

sudo add-apt-repository \
    "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
    $(lsb_release -cs) \
    stable"

sudo apt update
sudo apt -y install docker-ce docker-ce-cli containerd.io

# permission settings(sudoなしでdockerコマンドを使用する設定)
sudo usermod -aG docker vagrant
sudo systemctl restart docker

exit 0
```

直接Vagrantfileにインストール用のコマンドを記載することもできますが、
可読性と管理のし易さを考慮してshellに分けました。

## Vagrantfileの修正

上記のshellを実行したり、開発環境を整えるためにVagrantfileに修正を加えます。

```ruby
# config.vm.box = "ubuntu/bionic64" の下あたりに追記
config.vm.provision :shell, path: "dockerinstall.sh"

# docker-compose.ymlでportsを記載する場合、ホストとポートフォワードするには以下を追記
# これを記載するとhttp://localhost:8080 でアクセスできる
config.vm.network "forwarded_port", guest: 8080, host: 8080

# ホストのフォルダをマウントしたい場合
# 注意：docker, docker-composeのvolumeと同じにすると遅くなるのであくまでもホストからデータを移動したい時用
config.vm.synced_folder "./mnt", "/host_data"

# VMのスペック調整
# config.vm.provider "virtualbox" do |vb| のコメントを解除
# 対応するend のコメントも解除
config.vm.provider "virtualbox" do |vb|
  # CPUのコア数設定
  vb.cpus = "2"

  # メモリ設定
  # 私はホストが16GBなので8192に設定しています
  vb.memory = "4096"
end
```

# いざ、実行

```bash
# config.vm.synced_folderを設定している場合は先にフォルダを作成しないとエラーになります
mkir ./mnt

# VM立ち上げ
vagrant up

# VMにssh
# VMから抜ける時はexit
vagrant ssh

# VM終了(ホスト側で実行)
vagrant halt
```

ここで一点注意
`vagrant halt`をすると起動中のコンテナも問答無用で停止します。(シャットダウンと同じイメージ)

# その他

私はVisual Studio Code(VSCode)を使用して開発しているのですが、Intellij IDEAやVSCodeを使用している場合は
リモート設定を行うとローカルで開発している感覚でコーディングができるのでおすすめです！

VimやEmacs派の方はそのままsshで開発できちゃいますね。

VSCodeでの設定例は割愛しますが、私は以下のリンクを参考に設定しました。
`Remote-SSH`という拡張機能を使用します。
https://qiita.com/hppRC/items/9a46fdb4af792a454921

Intellij IDEAはこのへん？？
https://pleiades.io/help/idea/editing-individual-files-on-remote-hosts.html