Windows on Vagrantでsync folderを高速に使う方法

  • 71
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

年末年始がタキオン粒子のごとく流れていって呆然としていますが、皆さんいかがお過ごしでしょうか。
年末年始は姉の手伝いでなぜかC#と戯れていました。Javaよりもいろいろアグレッシブですね、あれ。

Vagrant on Windowsの不満

そんなことは置いといて、私の現場の環境はWindowsですが、その上でVagrant + VirtualBox を動かしてLinuxをメインの作業環境としています。
Vagrantを使うということは、当然(?)共有フォルダも利用する、ということ・・・ですが。

皆さんご存知の通り、 VirtualBoxの共有フォルダはめちゃ遅いです。どんくらい遅いかというとかなり。

これがMacとかLinuxの上で動かしているんだったら、 VirtualBoxの共有フォルダが遅かったらNFSを使えばいいじゃない と言えるんですが、そもそもWindowsじゃないと動かないもの(現場先の都合)があるからWindowsな訳でして。

しかし、実際作業効率を考えると、遅いよりは早いほうが当然いいです。しかしWindowsでは基本的にNFSは使えないし、Vagrantのプラグインはかなり不安定だ・・・。
SMBという手がある意味一番現実的だが、いろいろ戦うのも面倒くさい・・・。

何より、VirtualBoxの共有フォルダでは、 inotifyがうまく動かない という大問題があり、これのせいで、webpackとかBrowserifyとか、ほかの様々なファイル変更をトリガーにして起動する処理がいろいろグダリます。

type: rsync

そこでこれの出番になります。Vagrant 1.5から導入された、rsyncを用いて共有を行う方式があります。実際には vagrant rsync-auto を利用するのですが。

この方式の特徴としては、

  • rsyncなのでファイルが多いと若干同期に時間がかかる
  • rsyncさえ動けば(ゲスト・ホスト両方)、ほかには特殊なものは必要無い
  • ゲスト側は ゲストネイティブのファイルシステムを使える

最後がある意味性能に対して一番効いてくるところです。VirtualBoxの共有ファイルシステムを利用しない分、ファイルアクセスが段違いで早いです。

また、ゲストのファイルシステムをそのまま利用できるので、inotifyの恩恵に預かることができるため、いろいろ自動で動かすときにかなり効きます。

が、当然いいことだけじゃありません。

  • ホスト→クライアントへの一方通行
    • 一応双方向も検討されているみたいですが、1.7でもまだ追加されてません。

これがあまりにも致命的です。Eclipseで編集してその結果を自動的にGulpでビルド、とかそういったことをやりたいけども生成物が見えねぇよー、ということになります。

これを解消するのが今回紹介する方法です。なんとなく予測がついた方もいるとは思いますが。
ちなみにこの方法、私もどこかの海外サイトで見つけて若干アレンジして利用している感じになります。

実践

例として、npmを利用しているプロジェクトということにしておきます。なのでnode_modulesをどうするか、ということもポイントになります。

それと、Windows側でもrsyncを利用できるようにしておく必要があります。一番確実なのはMinGWのrsyncを導入することですが、それについては導入済みってことで進めます。

Vagrantfileのsynced foldersの設定を次のようにします。

Vagrant.configure("2") do |config|

  config.vm.synced_folder "/main", "c:/work/main", type:"rsync", rsync__exclude: [".git/", "node_modules"]
  config.vm.synced_folder "/main/public", "c:/work/main/public"
end

ぶっちゃけこの設定のやり方だけが大事です。 全体をrsyncして、一部をデフォルトの共有フォルダにする ということになります。

この場合、gulpやgruntを動作させるのは /main直下 になります。

実際にいじるのは上の例だと、C:¥work¥main の中です。例えばassetsディレクトリの下をいじると・・・

  1. rsync-autoが変更に反応して/mainへ変更を反映
  2. /mainで起動しているgulp/gruntなどが変更に反応
  3. /main/publicへ生成物を書き込む
  4. 生成物のディレクトリはVirtualBoxの共有フォルダなので、C:¥work¥main¥publicに生成物が書き込まれる

という形にできます。若干遠回りしてそうですが、実際にやるとrsync-autoの反映は2〜4秒くらいで終わりますので、以外と早いです。

何よりこの方法の場合、gulp/gruntの起動が、c:¥work¥main全体をVirtualboxの共有フォルダとした時のおよそ倍近く早くなります。
ただし、node_modulesをbind mountした場合になりますが・・・。

まとめと注意

基本的には、 全体をrsync、一部だけ共有フォルダ です。ただ、注意するべき点があって、それは rsyncする対象を多くしすぎない ということです。

node_modulesはその典型で、迂闊に入れると数万ファイルが同期される羽目になって、五分とか起動時とrsync-autoの開始時に待たされます。また、単純にファイルが多くなるので重くなります。
その辺は注意しておく必要があるとは思います。

しかし、若干の注意を払えば、Windowsでもそれなりに高速で、ちゃんとファイル変更のトリガーも働く、というのは結構いいんではないかと思います。

ほかにもっといい方法がないかは随時探しています。もっといい方法があれば教えていただければと思います。