Edited at

Rails + Docker Compose な環境を Docker for Mac から Vagrant に移行する


Docker for Mac を捨てたい

とある Rails プロジェクト (ここでは仮に kemurikusa プロジェクトとする) では、Rails サーバや Action Cable, Delayed Job, PostgreSQL を Docker Compose で動かすようにしている。僕のマシンは Mac なので、Docker を動かすのに Docker for Mac を使っている。しかし Docker for Mac を使っていて 2 つの致命的な問題に遭遇した。

ひとつは「com.docker.hyperkit プロセスの CPU 使用率が 150 〜 300% という高数値のままになってしまう」という問題だ。

docker/for-mac » Issue #1759 » High CPU Utilization of Hyperkit in Mac

上記の issue でも様々な議論がなされているが、僕の環境ではついぞ根本解決しなかった。

もうひとつはホストとコンテナ間のファイル共有が遅いという問題だ。

docker/for-mac » Issue #77 » File access in mounted volumes extremely slow

これを解決するために docker-sync というツールを使っていた。このツールではホストのファイルを直接マウントする代わりに、専用の外部ボリュームを用意して、そのボリュームとローカルを rsync などのツールを使って同期する仕組みだ。しかし、同期のタイミングにどうしてもラグが生じてしまうのがストレスだった。他にも設定ファイルで cached を使うという方法もあるが、docker-sync よりもパフォーマンスは劣っていた。

以上により Docker for Mac を使い続ける意思を完全に失ってしまった :sob:


Vagrant への移行


はじめに

Docker for Mac 以外の方法を模索していた結果 Vagrant で Linux 環境を構築して、そこで Docker Compose を動かすことにした。その結果、ホスト (Mac) とゲスト (Linux) のファイル共有の速度も速く、VirtualBox プロセスの CPU 使用率も落ち着いている。ゲスト OS は軽量と噂の CoreOS を採用した。


手順

前提として VirtualBoxVagrant をインストールしておく必要がある。また docker-compose.yml から docker-sync に関する記述を消す。


docker-compose.yml

-      - src-sync:/src:nocopy

+ - .:/src

- src-sync:
- external: true

CoreOS に対応した Vagrantfilecoreos/coreos-vagrant で提供されている。まず ここ から Vagrantfile をダウンロードして、Rails プロジェクトである kemurikusa プロジェクトのルートに配置する。

次に Vagrantfile を次のように書き換える。

🔽 VM のメモリを増やす。さもないと bundle install 時に Nokogiri のインストールで失敗した。


Vagrantfile

-$vm_memory = 1024

+$vm_memory = 2048

🔽 ポートフォワードの設定を行う。3000 は Rails、28080 は Action Cable のポート。


Vagrantfile

-$forwarded_ports = {}

+$forwarded_ports = { 3000 => 3000, 28080 => 28080 }

🔽 ホスト (Mac) の kemurikusa プロジェクトとゲスト (CoreOS) の /home/core/kemurikusa と同期する。


Vagrantfile

-      #config.vm.synced_folder ".", "/home/core/share", id: "core", :nfs => true, :mount_options => ['nolock,vers=3,udp']

+ config.vm.synced_folder ".", "/home/core/kemurikusa", id: "core", :nfs => true, :mount_options => ['nolock,vers=3,udp']

🔽 Vagrantfile(1..$num_instances).each のブロック内のどこかに次の行を追加する。


Vagrantfile

config.vm.provision :shell, path: 'vagrant/provision.sh'


🔽 kemurikusa プロジェクトの vagrant/provision.sh に次のシェルスクリプトを配置する。このシェルスクリプトはゲスト (CoreOS) に docker-compose をインストールするためのもので、初回の vagrant up 時にのみ実行される。


vagrant/provision.sh

DOCKER_COMPOSE_VERSION="1.23.2"

mkdir -p /opt/bin
curl -s -L https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-`uname -s`-`uname -m` > /opt/bin/docker-compose
chmod +x /opt/bin/docker-compose
docker-compose -v

ここまでで準備完了だ。あとは vagrant up を実行して VM を起動する。その後 SSH で VM にログインし、思う存分 docker-compose コマンドを実行すればいい :relaxed:

🔽 ホスト (Mac)

$ vagrant up

$ vagrant ssh

🔽 ゲスト (CoreOS)

$ cd kemurikusa

$ docker-compose up -d


参考