2020/11/04

Laravel Homestead Windows Folder Sync Issue

目前工作是基於 Laravel 開發公司產品,系統環境是 Windows,開發環境安裝了 Homestead,Homestead 是 Laravel 官方釋出,使用 Vagrant 安裝 Ubuntu,透過 config 可配置出 Laravel 開發需要的所有內容,包含 PHP(多種版本)、Apache 或 Nginx 提供選擇、Database、Redis 等等,Windows 以及 Mac 都可用,對 Windows user 來說最大的好處是開發環境可以較接近 production 環境(unix base)。

虛擬機器的工作模式多半會跟實體環境 mount 共同目錄,這樣可以直接在本機編輯檔案,虛擬環境連結的的內容會即時更新,但使用 Homestead 開發時一直遇到問題,例如在 vm 環境無法刪除某些檔案,或者是專案從 gitlab 下載以後 compose install 時會有錯誤訊息,像是:

[ErrorException]
  include(/home/vagrant/code/laravel/vendor/phpstan/extension-installer/src/Plugin.php): failed to open stream: No such file 
  or directory

只要把檔案放置在非 sync 的目錄下執行就不會有問題,因此我選擇了從別的地方 composer install or update 之後再複製到 sync 目錄,一直到日前我要開發新專案直接 new 一個新的目錄出後發生了更多大大小小的錯誤,包括測試會中斷,問題多到我無法像維護先前專案那樣換目錄執行套件安裝就好了,因此必須徹底解決這個問題。

其實問題很明顯,Windows sync 到 VM 後一定被外部的 Windows 影響到了目錄或檔案的權限,所以解法就朝變更 sync 方式發想,Vagrant 官方有提到幾種 sync 方式。

NFS

其中有一段文。

Windows users: NFS folders do not work on Windows hosts. Vagrant will ignore your request for NFS synced folders on Windows.

所以我就連試都沒試了。

RSync

Rsync 只能單方推送,我在 Windows 改變的檔案可以進去 VM,但在 VM 裡面執行產生的檔案不會同步回來,所以也不行。

SMB

Samba 有成功,之前發生的問題沒有了,但他非常慢,非常慢或許可以忍,但使用 SAMBA 後跑 unittest 會跑到 server 掛掉,這可就不能接受了。

上述方法使用無效以後,我還試了 WSL 以及 Multipass,WSL 我裝了 Ubuntu 20,但他 mount 的結果跟 Homestead 狀況一樣,multipass 也一樣,multipass 另外一個 issue 是如果使用 virtualbox 的話在 Windows 環境無法發派 IP,那你根本不能用 domain name 或 IP 進行測試,除非改用 hyper-v。

正當我試了一切想要放棄,打算使用 remote ssh 工作的時候,突然翻到 Homestead 有這麼一段說明:

To enable NFS, you only need to add a simple flag to your synced folder configuration:

When using NFS on Windows, you should consider installing the vagrant-winnfsd plug-in. This plug-in will maintain the correct user / group permissions for files and directories within the Homestead box.

What?

於是我安裝了 vagrant-winnfsd,然後 homestead 裡面配置了:

folders:
    - map: ~/code/project1
      to: /home/vagrant/project1
      type: "nfs"

所有問題都解決了,一切正常,而且速度很快,Vagrant 官方那段是在莊孝維嗎,為了解決這個問題我花了快一週,之後其他 Vagrant 配置也都會指定 sync 類型。

Vagrant.configure("2") do |config|
  config.vm.synced_folder ".", "/vagrant", type: "nfs"
end

很多東西解法其實很簡單,但有可能是前人嘗試了很久的結果,因為我順利解決了,所以留下這篇文章希望可以幫助到跟我遇到一樣問題的朋友。

沒有留言: