Vagrant Rsync Synced Folder を使って仮想環境内のコードをホスト上のエディタから編集するというお話

前置き

Web アプリケーションの開発において動的なページのコーディングをするとなると、なるべく本番環境に近いモノを用意したくなるのは自然なことです。一昔前であれば XAMPPMAMP といったパッケージをホストマシン上にインストールしてローカルな開発環境を用意するのが、僕らフロントエンドエンジニアの間では一般的でした。一方でサーバーサイドの開発を主としたエンジニア達は、VirtualBoxVMWare といった仮想環境を使うことで本番環境と殆ど同じモノを用意するのが当たり前でした。確かに Linux や Windows Server 上で動くものを作るとなるとこの手法を使うのは至極当然なのですが、サーバーに関する知識が求められるのと、色々と手順を踏んでいく上で途中でミスに気付かずそのまま詰んでしまうなど、フロントエンドエンジニア1)\(^o^)/ わたしのことですにとっては何かとハードルの高いものでした。

img-vagrant_logo

それがここ1,2年の間に Vagrant が登場したことによって状況が一変します。VirtualBox 上に仮想環境を構築するというのは同じなのですが、構築に必要な操作の多くを自動的に行なってくれる様になりました。多少なりとも黒い画面を使う必要はありますが、それでも操作手順が劇的に減ることのメリットには変えられません。

しかも Vagrant を使って作られた仮想環境は簡単にパッケージ化することができ、これを使いまわすことで開発メンバー間で全く同じ環境に揃えることが出来るようになったり、使っている上で何かうまくいかないことがあったら気軽に構築し直すことが出来るようになりました。

何より本番環境と遜色ないモノが開発環境として使えるのが大きいです。「あれ?ローカルでは動いてるのに本番では変なエラーがでるんだけど…?(´・ω・`)」といった事案が激減するのは、業務効率を考える上でとても重要な事です。

コードはどこで書くの? ホストマシン or 仮想マシン?

img-sublimetext_logo

本番環境に近いモノが簡単に作れるようになったまでは良いのですが、開発したコードを実行する環境が仮想マシン内(※以下、ゲストマシン)にあるとなると新たな問題が浮上してきます。僕の周囲のエンジニア勢は Vim というテキストエディタで開発するのが一般化しています。そのためゲストマシンに直接Vimをインストールしてその場でコードを書くことが出来るのですが、僕は Sublime Text というエディタを使う人なのでコードはホストマシン上でしか書くことが出来ません。いちいちコードを編集して保存する度にゲストマシンに転送するようでは本末転倒です。何かいい方法はないものでしょうか?

Vagrant ver 1.5で追加された Rsync Synced Folder

一言で説明すると、ホストマシンとゲストマシン間でのファイルの転送ならびに同期が出来る機能です。元々 VirtualBox には Shared Folder というホストマシンとゲストマシンが中身を共有することができるフォルダというのがあるのですが、作業ディレクトリもそこに限定されてしまうなどイマイチ使い勝手に欠けるものでした。Rsync Synced Folder は Rsync2)Mac OS X であれば標準で備えています。 という機能を利用して同期するものであり、動作がシンプルで非常に高速というメリットがあります。しかもゲストマシン側はネイティブなファイルシステムがそのまま利用出来るので、Synced Folder の仕様に影響されるといった心配がありません。nfs(Network File System) のようにホストマシン側でデーモンを起動することもありません。とにかくシンプルです。

パーミッション?そんなものは犬にでも食わせておけ。

Rsync Synced Folder を使ってみる

前提条件

  • ホスト: Mac OS X Mavericks
  • ゲスト: CentOS release 6.4 (Final)
  • Vagrant 1.6.3

ホストマシンは Mac OS X を前提に話を進めます。ゲストマシン側にも Rsync がインストールされている必要がありますが、主要な OS であれば Vagrant が勝手にインストールしてくれるようです。手持ちの開発環境は Cent OS ですが、yum -y install rsyncが実行されていました。

Vagrant の設定

Vagrantfileを開いて以下のように設定します。

config.vm.synced_folder "./path/to/host/dir", "/path/to/guest/dir",
  type: "rsync",
  owner: "vagrant",
  group: "vagrant",
  rsync__exclude: [".git/", "vendor/"]

上記のコードは、通常であれば Vagrantfile の42行目あたりにコメントアウトされているかと思います。それを各自が必要に応じて書き換えます。

config.vm.synced_folderというメソッドに対して必要な引数を渡してあげます。第一引数に同期元となるディレクトリ(ホストマシン側)、第二引数に同期先となるディレクトリ(ゲストマシン側)を渡します。以降はオプションです。

type

同期されるフォルダの種類を指定します。rsyncとすることで Rsync を使った同期処理が実行されます。

owner

ゲストマシン側におけるファイル・フォルダの所有者を指定します。デフォルトは SSH ログインしたユーザーとなり、通常であれば Vagrant ユーザーが指定されるので、未設定でも特に問題ないでしょう。

group

owner 同様、ゲストマシン側におけるファイル・フォルダの所有グループを指定します。デフォルトは SSH ログインしたユーザーとなり、通常であれば Vagrant ユーザーが指定されるので、こちらも未設定で特に問題ないでしょう。

rsync__exclude

同期させたくないファイルやディレクトリを指定します。上記の様にカンマ区切りで複数指定することができます。デフォルトで".vagrant/"が指定されており、オプションで指定したものはコレに追加される形で設定されます。".git""vendor/"といったディレクトリを指定しておくとよいでしょう。

公式ドキュメントで全てのオプションを知ることが出来ます。

同期させてみよう

ゲストマシンが起動している状態で以下のコマンドを実行します。

vagrant rsync
==> default: Rsyncing folder: /path/to/host/dir => /path/to/guest/dir
==> default:   - Exclude: [".vagrant/", ".git/", "vendor/"]

設定に問題が無ければこれだけで同期処理が完了します。動作も軽快です。同期処理は上記のコマンド以外にvagrant up,vagrant reload,vagrant provision を実行した際にも行われます。

同期処理を自動でやってほしい

ファイル編集の度に上記のコマンドを実行するのは手間です。以下のコマンドを実行することで Synced folder に指定したディレクトリが監視され、配下のディレクトリ含めファイルに変更が入ると自動的に同期処理が実行されます。

vagrant rsync-auto
==> default: Doing an initial rsync...
==> default: Rsyncing folder: /path/to/host/dir => /path/to/guest/dir
==> default:   - Exclude: [".vagrant/", ".git/", "vendor/"]
==> default: Watching: /path/to/host/dir

ホストマシンでコードを書いてゲストマシンで実行するスタイルでは、上記コマンドを実行するのが良いでしょう。

注意点

同期はホストマシン -> ゲストマシンのみ

時点で、同期はホストマシンからゲストマシンという流れしか出来ません。僕個人としてはこれだけでも充分なのですが、ゲストマシンからホストマシンへの同期をしたいという Issue が出ているようです。

Rails アプリ開発する際はホストマシンとゲストマシン両方で gem install を実行すること

Rails に限った話ではないと思いますが、複数人で Rails アプリを開発していると誰かが Gem を追加したコードを Master ブランチにマージし、自分がそれを Pull して新しく開発を始めようとすると、Rails からgem installを実行するよう警告が出るでしょう。すかさずゲストマシン内で実行すればいいのですが、この際Gemfile.lockというファイルが更新されます。一方ホストマシン側のGemfile.lockは更新されないので、この時点で差分が発生します。ということはホスト側でファイル更新する度に古い内容の Gemfile.lock で上書きされることになるます。これではゲスト側の Rails を再起動する度に Gemfile.lock がおかしいということでgem installをするハメになります。何かと面倒な上、本番環境へのデプロイ時にも影響しかねないので、必ずホストマシン側でも実行するようにしましょう。

おわりに

開発環境と実行環境が完全に分離されるので、とても重宝しています。Vagrant サマサマですね。

脚注

脚注
1 \(^o^)/ わたしのことです
2 Mac OS X であれば標準で備えています。