Vagrant(VirtualBox)でディスクアクセスが遅い問題の対処法

Windows + Vagrant + VirtualBox で Laravel を動かすと、ローディングにかなりの時間がかかって仕事が進まなかったという問題の対処方法を紹介します。NFS を使用する方法です。

Virtual Box の共有フォルダ機能は遅い

ホスト側とゲスト側でプログラムファイルなどを共有するためにVirtualBoxに共有フォルダ機能が存在しますが、デフォルトの共有方法を用いるとかなり遅くなります。
仕事でLaravelを使ったWebサイトをVirtualBoxで構築(指定されたので...)していたところ、Windows環境でもMac環境でも1ページ読み込むのに5秒ほどかかり、まともに仕事ができない状態になってしまいました。
デフォルトのファイル共有機能は、比較的安定性は高く、多くのOSで使用できるのですが、メモリキャッシュなどの機能を使用していないため、ディスクアクセスが遅いのが欠点です。
一方、Laravelは大量の依存ファイルを読み込むのでディスクアクセスが大量に発生します。そのため表示が遅くなります。

対処方法

Dockerなどの仮想化技術が使用できるツールに切り替えができるのであれば、切り替えるのをおすすめします(ちなみにDocker ToolBoxはVirtualBoxを使用するので意味ありません...)。それができない場合は、NFSでマウントする機能を使用します。
仕組みは公式ドキュメントをご確認ください。
NFS - Synced Folders | Vagrant by HashiCorp
https://www.vagrantup.com/docs/synced-folders/nfs

Windows の場合はプラグインが必要

公式ドキュメントには下記の記載があり、Windowsホストでは使えないと書いてあります。
Windows users: NFS folders do not work on Windows hosts. Vagrant will ignore your request for NFS synced folders on Windows.
ところが、なんとWindowsでNFS機能が使用できるプラグイン(vagrant-winnfsd)がコミュニティに存在します!素晴らしすぎて感謝してもしきれません。
winnfsd/vagrant-winnfsd: Manage and adds support for NFS for Vagrant on Windows.
https://github.com/winnfsd/vagrant-winnfsd
ホスト側がWindowsの場合は下記コマンドでプラグインを先にインストールしておいてください。
vagrant plugin install vagrant-winnfsd

NFS に変更する方法

NFSに変更するにはVagrantFileの共有ディレクトリの設定にあたる部分を変更する必要があります。
先ほどの公式ドキュメントに記載されていた通り、type: "nfs" を追加するだけで使用できます。
例えば下記のように設定します。
config.vm.synced_folder ".", "/var/www/src", type: "nfs"
尚、private_networkが必要です。IPは例ですが、静的IPアドレスだとトラブルがすくないです(.1はホスト側で予約されていますので.2以上にする必要があります)。
config.vm.network :private_network, ip: "192.168.2.2"
(とくにMac)ファイアウォールに引っかかりやすいので、うまく動作しない場合はファイアウォールの設定をご確認ください。

CSSやJavaScriptが壊れてしまう場合

環境の組み合わせによっては、sendfileの影響でCSSやJavaScriptが壊れてしまう場合があります。その場合の対処方法はこちらをご確認ください。
仮想環境で開発中 JavaScript が途中で途切れて壊れる場合の対処法
https://bicstone.me/enablesendfile-js-broken/

シンボリックリンクが動作しない場合

Laravelでは、シンボリックリンクを貼らないといけない機能(ファイルストレージ)があります。
ファイルストレージ 6.x Laravel
https://readouble.com/laravel/6.x/ja/filesystem.html
ホストがWindowsの環境では、なぜかシンボリックリンクが壊れてしまい利用できませんでした。
$ ls -l storage
lrwxrwxrwx 1 root root 0 Dec 24 02:12 storage -> ../../storage/app/public
$ cd storage
cd: no such file or directory: storage
vagrant-winnfsd プラグインの影響なのか、Windowsの影響なのかわかってはいません。
私は、Publicディレクトリのみ、標準の共有ファイルに設定しました。下記のようなイメージです。
config.vm.synced\_folder ".", "/var/www/src", type: "nfs", rsync\_\_exclude: "./public"
config.vm.synced\_folder "./public", "/var/www/src/public"
これで、高速化しつつ、ファイルストレージも使用できる環境になりました。それでもLaravelは遅いですけどね。。。