Vagrant Cachier Plugin
There`s one plugin for Vagrant which I love to promote in my talks and this is the Cachier plugin. When giving my talks and mentioning the plugin I realized that not many people are aware of the plugin. That`s the main reason I write the following lines. The downside of Vagrant is what whenever you destroy a virtual machine and build it again all packages (eg. .deb packages for the OS or Composer packages for the application) need to be downloaded again. Downloading and installing a lot of packages can be quite time consuming which in turn means developers try to avoid it. Which in turn means no one regularly checks if provisioning of the virtual machine still works as it should. The Cachier plugin is the solution for that problem. As the name implies the plugin will cache the downloaded packages and re-use them when possible. To achieve that the plugin will link several folders of the virtual machine back to the host, so that the packages are actually stored on the host, not the vm. Very clever.
To be able to use the Cachier plugin you have to install it first via vagrant:
vagrant plugin install vagrant-cachier
To make sure that your virtual machine is using the caching mechanism you have to explictly enable it via your Vagrantfile. Add the following files to your Vagrantfile:
# enable vagrant-cachier plugin if plugin is installed if Vagrant.has_plugin?("vagrant-cachier") config.cache.scope = :box config.cache.enable :apt config.cache.enable :apt_lists config.cache.enable :composer config.cache.enable :npm end
The configuration logic is wrapped in an if statement to make sure that configuration is done only when the plugin is installed. This way vagrant will also run when the plugin is not installed. It is said that the Cachier plugin is able to detect which caches are needed but I love to explictly turn them of, just for the sake of it. In the example above the plugin with cache apt packages, Composer packages and npm packages. The packages are stored for the box scope which means other projects using the same base box will also use the same cache. As an alternative you can use the :machine scope to store the packages just for the specific machine you are working with.
There was one downside in our setup which in the end was easy to fix: The Cachier plugin does not set up the caching folders for the root user but for any other user. Since we use a bootstrapping script in our virtual machine to run puppet and from our puppet code let Composer run the root user actually was the one running Composer and not using the cached packages. The fix was simple and easy: Before we let puppet run in our bootstrap script we manually symlink the respective folders for the root user:
# Create .composer/cache symlink for root if vagrant-cachier is active if [ -d /tmp/vagrant-cache/composer/ ]; then if [ ! -d /root/.composer ]; then mkdir /root/.composer fi if [ ! -L /root/.composer/cache ]; then ln -s /tmp/vagrant-cache/composer/ /root/.composer/cache fi fi
The same solution was needed for caching the npm packages as root:
# Create .npm symlink for root if vagrant-cachier is active if [ -d /tmp/vagrant-cache/npm/ ]; then if [ ! -L /root/.npm ]; then ln -s /tmp/vagrant-cache/npm/ /root/.npm fi fi
By using the Cachier plugin we could reduce the provisioning time in one of our projects from about 20min to about 6min which is a clear win for us.