Home > Vagrant > Vagrant 1.5 で追加された Rsync Synced Folder が良い

Vagrant 1.5 で追加された Rsync Synced Folder が良い

この記事の所要時間: 1025

Vagrant 1.5 がリリースされました。1.1 以来の big change ということで、目新しい機能が追加されています。

vagrant

目玉はやはり Vagrant Share だと思うのですが、その他にも Web システムの開発に Vagrant を使っている人には嬉しい機能が追加されています。

その一つが Rsync Synced Folder です。

Rsync Synced Folder

Vagrant には、ホストマシンとゲストマシンとでファイルを共有、同期する機能があります。

これにより、開発はホストマシンで行い、実行は LA(MP)P 環境であるゲストマシンで行うという、いいとこ取りができました。

この機能を実現する方法として、shared folder(VirtualBox の機能)や NFS を利用することができたのですが、これに rsync による同期が追加されました。

ホストマシンからゲストマシンへ rsync で同期を行います。

嬉しいこと

Rsync Synced Folder は、rsyncで同期を行うだけなので、ゲストマシン側はネイティブなファイルシステムが利用できます。つまり、synced folder の仕様に影響されなくなります。

パフォーマンス

分かりやすいメリットとしては、VirtualBox の shared folder に比べると、パフォーマンスが向上します。手元にある PHP アプリケーションでは、shared folder で 90 秒程度かかっていたユニットテストが、60 秒程度に短縮しました。

また、NFS と違って、ホスト側でデーモンを起動しておく必要が無いのも大きなメリットです。

パーミッション

shared folder では、パーミッションをディレクトリやファイルごとに設定することができなかったのですが、rsync を利用すれば、ゲストマシンからは通常のファイルシステムなので何も支障がありません。

ただ、現状の Rsync Synced Folder では、同期時にファイルオーナーを強制的に書き換える仕様になっているので、この点については留意しておく必要があります。(後述)

自動更新機能

この rsync は、基本的にはvagrant up, vagrant reload, vagrant provision、そして今回新設されたvagrant rsyncコマンド実行時に行われます。

これだとファイルを変更する度にコマンドを実行するのが面倒になるのですが、vagrant rsync-autoコマンドを実行することで、自動で同期を行うことができます。設定で同期対象となったディレクトリに変更があれば、自動で同期処理を行います。

どのようなプロバイダでも同期可能

AWS や DigitalOcean のようなクラウドサービスをプロバイダとして使っている場合も、rsync-auto による自動同期が可能です。

コードを変更すると、クラウド上のサーバに自動で同期されます。

要件

この機能を利用するには、ホストとゲストの双方にrsyncコマンドが必要になります。

ホストについては、OSX であればデフォルトでインストールされています。

ゲストについては、もしインストールされていなくても、主要な OS については、Vagrant が自動でインストールしてくれます。例えば、RedHat 系であれば yum -y install rsyncが実行されます。

これは気が効いてますね。

設定

Vagrantfile の synced folder の設定で、type=rsyncを指定します。

config.vm.synced_folder "src", "/share", type: "rsync"

設定には下記のようなオプションがあります。

  • rsync__args
    rsync コマンドに渡す引数です。デフォルトでは["--verbose", "--archive", "--delete", "-z"]が指定されています。

  • rsync__auto
    rsync-auto による自動同期の対象にするかどうかです。デフォルトは、trueです。

  • rsync__exclude
    同期の対象外にするファイルやディレクトリを指定します。デフォルトでは[".vagrant/"]が指定されています。

例えば、.git ディレクトリは同期対象から外すなら、下記のようにrsync__excludeを指定します。

config.vm.synced_folder "src", "/share", type: "rsync", rsync__exclude: [".git/"]

手動で同期する

vagrant upvagrant reloadvagrant provisionvagrant rsyncを実行すると、Vagrantfile の synced_folder で指定したディレクトリについて、rsync による同期を行います。

ファイルを同期したいだけなら、vagrant rsyncを実行します。

$ vagran rsync
==> default: Rsyncing folder: /path/to/src/ => /share

自動で同期する

自動で同期するには、vagrant rsync-autoコマンドを実行します。コマンドを実行すると、synced_folder で指定した同期対象のディレクトリを監視します。

$ vagrant rsync-auto
==> default: Watching: /path/to/src/

同期対象のディレクトリに変更があると、自動でrsyncが実行され、同期されます。

$ vagrant rsync-auto
==> default: Watching: /path/to/src/
==> default: Rsyncing folder: /path/to/src/ => /share

ホストで開発して、ゲストで実行するというスタイルなら、常に rsync-auto を実行しておくと良いでしょう。

注意点

ホストからゲストの同期のみ

現在のところ、同期はホストからゲストの一方向のみです。

ゲストからホストへファイルを転送するvagrant rsync --pullというのが、issue で提案されているので、いずれ実装されるかもしれません。

https://github.com/mitchellh/vagrant/issues/3062

rsync 実行でファイルオーナーが変更される

rsync-auto を使っている時に気づいたのですが、rsyncの実行前にゲスト側の同期ディレクトリに対してchown -R vagrant /pathを実行して、ファイルオーナーを変更しています。

同期対象ディレクトリを丸ごとホスト側と同期するなら特に問題無いのですが、ゲストでアプリケーションが実行時に生成するファイル(ログファイル等)をrsync__excludeオプションで同期対象外にしている時に問題が発生します。

例えば、アプリケーションがapp/storage/log/以下にログファイルを出力する場合、このディレクトリを同期対象外とします。

config.vm.synced_folder "src", "/share", type: "rsync", rsync__exclude: [".git/", "app/storage/log/*"]

この時、アプリケーションを実行するとゲストでは、下記のようにアプリケーションの実行ユーザである apache ユーザによってログファイル(laravel.log)が生成されます。

[vagrant@localhost /share]$ ls -la app/storage/log/
drwxrwxrwx. 2 vagrant vagrant     4096  3月 13 05:51 2014 .
drwxrwxrwx. 7 vagrant vagrant     4096  2月 13 07:50 2014 ..
-rw-rw-rw-. 1 vagrant vagrant       13  2月 13 07:50 2014 .gitignore
-rw-r--r--. 1 apache  apache      5394  3月 13 05:51 2014 laravel.log

次にホスト側で vagrant rsyncで同期します。

$ vagrant rsync
==> default: Rsyncing folder: /path/to/src/ => /share

ゲスト側では laravel.log は、同期対象外となっているのでファイルはそのまま残っています。しかし、ファイルオーナーが vagrant に変更されています。

[vagrant@localhost /share]$ ls -la app/storage/log/
drwxrwxrwx. 2 vagrant vagrant     4096  3月 13 05:51 2014 .
drwxrwxrwx. 7 vagrant vagrant     4096  2月 13 07:50 2014 ..
-rw-rw-rw-. 1 vagrant vagrant       13  2月 13 07:50 2014 .gitignore
-rw-r--r--. 1 vagrant apache      5394  3月 13 05:51 2014 laravel.log

この状態でアプリケーションを実行すると、ログファイルへの書き込み権限が無いためにエラーが発生します。

Vagrant のソースを見ると、plugins/guests/linux/cap/rsync.rb で、rsync 前に実行する処理が定義されているのですが、たしかにsudo chown -Rが実行されています。

        def self.rsync_pre(machine, folder_opts)
          username = machine.ssh_info[:username]

          machine.communicate.tap do |comm|
            comm.sudo("mkdir -p '#{folder_opts[:guestpath]}'")
            comm.sudo("chown -R #{username} '#{folder_opts[:guestpath]}'")
          end
        end

おそらく、vagrant rsync を実行する際に、Permission Denied が出ないように、一括でchownしているのだと思うのですが、ここは注意しておく必要があります。

rsync-auto を忘れる

これはケアレスミスなのですが、VirtualBox の shared folder や NFS であれば、自動で同期するので、ホストでコードを変更したのに、ゲストに反映されずに「あれ?」となったことが何度かありました。

vagrant rsync-autoを実行しないと、自動で同期されないので、忘れずに。

さいごに

Rsync Synced Folder を使うことで、shared folder で気になっていた点が解決しそうです。なんといっても、ユニットテストが速くなるのはありがたいですね。

Pocket

follow us in feedly

Home > Vagrant > Vagrant 1.5 で追加された Rsync Synced Folder が良い

検索
フィード
メタ情報

Return to page top