In this blog post I am going to go over a useful trick that I have been using to minimize the time of provisioning a vagrant box. Basically what it is about is having two vagrant or more vagrant files in the project (depending on what you are doing) and a script that creates a vagrant box from one of the vagrant files, then use the box in the next one.
Example
We are going to setup a machine with some applications that takes some time to install (can be what ever). Then we are going to configure the installed applications after they are installed, that will be our second vagrant script. Our first vagrant file will be named Vagrantfile.Basebox and our main vagrant file will be named Vagrantfile.
Vagrantfile.Basebox
$centos_box = "centos/7" Vagrant.configure(2) do |config| config.vm.define "basebox" do |basebox| basebox.vm.box = $centos_box basebox.ssh.insert_key = false basebox.vm.synced_folder ".", "/vagrant", type: "virtualbox" basebox.vm.provision :shell, path: "long-running-task.sh" # more provisioning if needed end end
This will be the script that creates the base box. I chose centos because there is a little quirk that needs to be addressed ( addressed in the comments in the script )
create-basebox.sh
#!/usr/bin/env bash BOX_NAME=hx/base-centos TEST_IF_BOX_EXISTS=$(vagrant box list | grep $BOX_NAME) if [ "$1" = "-f" ]; then TEST_IF_BOX_EXISTS="" vagrant box remove $BOX_NAME if [ "$?" -ne 0 ]; then echo "Could not remove box, check if you have running machines using the box" exit 1 fi fi if [ "$TEST_IF_BOX_EXISTS" = "" ]; then echo "$BOX_NAME does not exist, creating $BOX_NAME" mv Vagrantfile Vagrantfile.tmp cp Vagrantfile.base.rb Vagrantfile vagrant up basebox vagrant halt basebox # Centos specific, if you are using a different distro, # the next couple of lines are not necessary vagrant up basebox vagrant halt basebox VBOX_INSTANCE=$(vboxmanage list vms | grep -oP "${PWD##*/}_basebox_[0-9_]*") vagrant package --base $VBOX_INSTANCE --output base.box # Handle paths differently when using cygwin if $(pwd | grep -q cygdrive) ; then BOX_FILE_PATH=$(echo "$PWD" | sed -E 's/\/cygdrive\/([a-z])(.*)/file:\/\/\/\1:\2\/base.box/') else BOX_FILE_PATH=$(pwd | awk '{print "file:" $1 "/base.box"}') fi vagrant box add $BOX_NAME $BOX_FILE_PATH vagrant destroy -f # Removing the box some times fails because the file handle has not been # released. So put a short sleep before the remove sleep 3 rm -f base.box rm Vagrantfile mv Vagrantfile.tmp Vagrantfile echo "Done creating $BOX_NAME" else echo "$BOX_NAME exists, moving on..." fi
Then we can use the base box in the our Vagrantfile.
Vagrantfile
$custom_box = "hx/base-centos" Vagrant.configure(2) do |config| config.vm.define "custombox" do |custombox| custombox.vm.box = $custom_box custombox.ssh.insert_key = false custombox.vm.synced_folder ".", "/vagrant", type: "virtualbox" custombox.vm.provision :shell, path: "config-task.sh" # more provisioning if needed end end
This way you can do the bulk of the work in the basebox, cutting down on the time that it takes to provision the boxes that build on top of it.
Usage
./create-basebox.sh
vagrant up
One thought on “Vagrant tricks – Creating local baseboxes”