ずっとWindowsでの開発環境構築を試しているのですが、とりあえずベストではないにしてもベターまで来たかなと思うのでメモを残します。過去のトラブルはこちら。
なお、Hyper-Vを使わずにVirtualBoxを使うほうを強くお勧めします!(ハマりどころが少ないだろうから)
VagrantでHyper-Vを選ぶ際のTips
VagrantでプロバイダをHyper-Vにすることができますが、制限事項がかなり多いです。
フォルダ共有にはsmbを選んだほうがよさそう
フォルダ共有はNFSがいいという意見がネットでは多いのですが、どうもVirtualBoxだとうまく動くみたいなのですが、Hyper-Vだと動かない模様。試行錯誤したのですが、私にはわからなかったため、smbを使って共有しています。以下のissueでは、Hyper-VだったらSMBでいいという話になっているみたいでした。
また、SMBでフォルダ共有を行う場合は、vagrant up
を実行する都度、Windowsにログインするためのユーザ名とパスワードの入力を求められるので、これを最初はVagrantfileに直書きしていたのですが、vagrantのdotenvプラグインがあるとのことだったので、これを使うようにしました。
vagrant plugin install dotenv
これで、.env
ファイルにログイン情報を移動させることができます。
SMB_USER = "" # Windowsのユーザ名 SMB_PASS = "" # Windowsのパスワード
そして、これを使うようにVagrantfile
を編集します。
# -*- mode: ruby -*- # vi: set ft=ruby : Dotenv.load # 追加 Vagrant.configure("2") do |config| config.vm.box = "bento/ubuntu-18.04" config.vm.provider "hyperv" config.vm.synced_folder "~/vagrant", "/vagrant", create: true, type: "smb", mount_options: ["vers=3.0"], smb_password: "#{ENV['SMB_PASS']}", smb_username: "#{ENV['SMB_USER']}" # 略 end
これでOK…と思ったら、ところがどっこい、vagrant up
するとホストのIPが見つからないというエラーで共有できませんでした。これは、接続する仮想スイッチのネットワークをパブリックとワークからプライベートネットワークにすれば解決しました。上のほうに載せている過去記事を見ていただければと思います。
Vagrantのポートフォワーディングは使えない
とりあえずこれで、Windows側とHyper-V上のUbuntuでフォルダ共有できたので、Vagrantfileを修正してポートフォワードするようにして、Ubuntu側でRailsを起動してみました。
# 追加 config.vm.network "forwarded_port", guest: 3000, host: 3000, host_ip: "127.0.0.1"
が、うんともすんとも言いません…。調べてみると、どうもHyper-Vの場合はネットワークの設定は全て無視されるようです。 なので、上記の設定は何の意味もない模様。
では、Hyper-Vの場合はどうすればいいのか?Windows側でポートフォワーディングの設定を行う必要があります。参考にちょうどよいページがありました。
これを参考に、設定してみます。192.168.212.51
は、VM側に設定されているIPです。
netsh interface portproxy add v4tov4 listenport=3000 listenaddress=127.0.0.1 connectport=3000 connectaddress=192.168.212.51
これで、VM側の3000番ポートがホスト側にポートフォワードされるようになりました。Windowsのブラウザでhttp://localhost:3000
にアクセスしたら、Ubuntuで起動中のRailsアプリにアクセスできました!なお、Railsアプリを起動するときはbin/rails s -b 0.0.0.0
を忘れずに!!
これで、とりあえずやった!というお気持ちを表明。
うおおー!やっとvagrant & Hyper-Vで動かしたRailsアプリを http://localhost:3000 で見ることができた!
— パトラッシュ@RubyKaigi参加してました (@patorash) 2019年5月1日
Hyper-Vの仮想スイッチ(Default Switch)は使えない
ここで、過去にPCを再起動したらVMのIPが変わっていたことを思い出しました。
しかしこれ、Windowsを再起動しても設定生きてるんかいな?再起動してみるか…。
— パトラッシュ@RubyKaigi参加してました (@patorash) 2019年5月1日
やっぱり再起動したらデフォルトスイッチのIPが変わったのでこれは辛い。自分で仮想スイッチを作るのが正解っぽい。
— パトラッシュ@RubyKaigi参加してました (@patorash) 2019年5月1日
ということで、Windowsを起動すると仮想スイッチのDefault SwitchのIPがコロコロと変わり、全く意味がない模様。
せっかくnetshでポートフォワードの設定を書いたのに、台無しです…。こうなると、自分で仮想スイッチを定義するのがよさそうです。しかし、自分で作った仮想スイッチだとVMにIPの割り当てを行ってくれず、VM側でIPを設定する必要がある模様。なんとか自動でIPをふる方法を調べていたのですが、見つからなかったので、公式の言う通りにしてみます。
仮想スイッチの作成とNATの設定
以降の処理は、PowerShellで、管理者権限で。まず、Switchを作ります。
New-VMSwitch -SwitchName "VagrantNAT" -SwitchType Internal
次に、Switchの情報を見ます。ifIndexが必要な情報となります。
Get-NetAdapter Name InterfaceDescription ifIndex Status MacAddress LinkSpeed ---- -------------------- ------- ------ ---------- --------- vEthernet (VagrantNAT) Hyper-V Virtual Ethernet Adapter #2 10 Up 00-15-5D-8F-1B-31 10 Gbps # 他は省略
次に、仮想スイッチにIPを割り当てます。今回は192.168.100.1
にしました。-InterfaceIndex
に先ほどのifIndexの値を指定します。
New-NetIPAddress -IPAddress 192.168.100.1 -PrefixLength 24 -InterfaceIndex 10
次に、NATネットワークを作ります。
New-NetNat -Name VagrantNATnetwork -InternalIPInterfaceAddressPrefix 192.168.100.0/24
これで、ネットワークは完成です。VMへのIPの割り当ては別途VMに入って行います。
VM側のIP設定を行う
VMはとりあえずvagrant up
を行います。IPは割り当てられませんが、作業にはvagrant ssh
が使えるので問題ありません。
vagrant ssh
を使ってVMの中に入り、IPを設定します。Ubuntu18.04からIPの設定方法が変わった模様です。
sudo vi /etc/netplan/01-netcfg.yaml
これで、以下のように設定しました。
network: version: 2 ethernets: eth0: addresses: - 192.168.100.2/24 gateway4: 192.168.100.1 dhcp4: false nameservers: addresses: - 8.8.8.8
nameserversは、192.168.100.1にしたらapt-getに失敗したので、8.8.8.8にしています。 そして、netplanの設定を反映します。
sudo netplan apply
これで、VMに固定IPが設定されました。
ポートフォワードの設定をやり直し
既存の設定は意味がないので、resetで削除し、先ほど登録したVMのIPでポートフォワードの設定をやり直します。
netsh interface portproxy reset netsh interface portproxy add v4tov4 listenport=3000 listenaddress=127.0.0.1 connectport=3000 connectaddress=192.168.100.2
これで完了!VM側でRailsアプリを起動したところ、http://localhost:3000
でアクセスできました🎉🎉🎉
うおおー!やっとvagrant & Hyper-Vで動かしたRailsアプリを http://localhost:3000 で見ることができた!(2回目) https://t.co/riOhjbnG76
— パトラッシュ@RubyKaigi参加してました (@patorash) 2019年5月2日
なお、PCを再起動しても問題ありませんでした!ただ、Vagrantを自動起動にしていたらSMBの共有に失敗していたので、vagrant reload
したらうまくいきました。
まだまだ開発環境としては問題がありそうなのですが(SMB上にRailsアプリを置いてrails sすると遅い…)、とりあえず動かせたので、よしとします。