HashiCorp Vagrant is a great tool to quickly get up and running with a development environment. In this blog post I’ll give some tips to make your life with Vagrant even better! You can find an example which uses these tips here.
Tip 1: The disksize plugin
Ever created a VM with a specific size for the disk and after using it for a while, you find out you would have liked to have a larger size disk? You can resize the VDI in for example VirtualBox, however that that is not sufficient to increase the size of logical volumes and partitions within the VM -> make the extra space available to use. If you ever tried to manually assign the extra space (like I did here), you’ll know this can be some work and has some risks involved. Wouldn’t it be nice if
(independent of the size of the disk the base box might have) you can ask Vagrant to give you the disk size you want to have?
Enter theĀ vagrant-disksize plugin.
Install it with
vagrant plugin install vagrant-disksize
And you can use it in your Vagrantfile like:
config.disksize.size = '75GB'
It will figure out what to do and do it!
Tip 2: The vbguest plugin
Getting tired of installing guest additions after each and every new installation and keeping them updated after a new version of VirtualBox is released? Mounting an ISO, installing the required dependencies, running the installerā¦ You don’t have to worry about those things anymore! The vagrant-vbguest plugin takes care of this for you.
Install it with:
vagrant plugin install vagrant-vbguest
And add to your Vagrantfile a line like:
config.vbguest.auto_update = true
This installs the correct version of the guest additions and also installs dependencies if required to for example build the module.
Tip 3: The reload plugin
The vagrant-reload plugin which is available here allows you to incorporate VM reboots inside your Vagrantfile. This can be quite powerful since it for example allows things like replacing kernel boot parameters and continue with the parameters set after the reboot.
First install the plugin:
vagrant plugin install vagrant-reload
And add something like below to your Vagrantfile and you’re set to go!
config.vm.provision :reload
You can add provisioners above and below this command. This (incorporating a reboot during the provisioning process) is something which is not possible with tools like kickstart (RHEL derivatives) and preseed (Debian derivatives) which automate the installation of Linux OSs. HashiCorp Packer also has a similar option (for Windows and probably also for Linux).
Tip 4: Install missing plugins
If I want to share a Vagrantfile, I want people to be able to use it without much local preparations. When my Vagrantfile depends on plugins such as above, it won’t work if they are missing. Luckily installing missing plugins is easy to automate within your Vagrantfile like below:
unless Vagrant.has_plugin?("vagrant-disksize")
puts 'Installing vagrant-disksize Plugin...'
system('vagrant plugin install vagrant-disksize')
end
unless Vagrant.has_plugin?("vagrant-vbguest")
puts 'Installing vagrant-vbguest Plugin...'
system('vagrant plugin install vagrant-vbguest')
end
unless Vagrant.has_plugin?("vagrant-reload")
puts 'Installing vagrant-reload Plugin...'
system('vagrant plugin install vagrant-reload')
end
This way you don’t have to first install the plugins before you can use the Vagrantfile. Inspiration from the Oracle provided Vagrantfiles here.
Tip 5: Execute a command once after a reboot
Suppose you want to have a specific command executed only once after a reboot. This can happen because a specific command could require certain files not to be in use or for example the vagrant user not to be logged in. You can do this with a pre-script (prepare), the reload plugin and a post script (cleanup). The below example should work for most Linux distributions:
Inside your Vagrantfile:
config.vm.provision :shell, path: "prescript.sh"
config.vm.provision :reload
config.vm.provision :shell, path: "postscript.sh"
Pre-script: prescript.sh
chmod +x /etc/rc.d/rc.local
echo ‘COMMAND_YOU_WANT_TO_HAVE_EXECUTED’ >> /etc/rc.d/rc.local
Post-script: postscript.sh
chmod -x /etc/rc.d/rc.local
sed -i ‘$ d’ /etc/rc.d/rc.local
The pre-script adds a line to rc.local and makes it executable. The postscript removes the line again.
Tip 6: Installing docker and docker-compose
For installing docker and docker-compose (and running containers) there are 3 main options.
Using Vagrant plugins
This is the easiest option and does not require specific provisioning file entries. The Docker provisioner is provided as part of Vagrant out of the box. Docker-compose requires the installation of a plugin.
vagrant plugin install vagrant-docker-compose
Inside your Vagrantfile
config.vm.provision :docker
config.vm.provision :docker_compose
Using these plugins, you might have to look into how you can force it to use a specific version should you require it.
Using a provisioning script and OS repositories
This is the option I usually choose. It provides more flexibility. Below are examples from a provisioning shell script. Docker and Docker Compose are usually present in the repositories provided by the OS supplier.
For Oracle Linux 7:
#Docker
yum install yum-utils -y
yum-config-manager --enable ol7_addons
yum-config-manager --enable ol7_optional_latest
yum -y update
/usr/bin/ol_yum_configure.sh
yum -y update
yum install docker-engine -y
systemctl start docker
systemctl enable docker
For Ubuntu bionic (18.04):
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
apt-cache policy docker-ce
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
apt-get update
apt-get -y install apt-transport-https ca-certificates curl gnupg-agent software-properties-common docker-ce docker-compose
Using the docker / docker-compose provided convenience scripts
#docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
#docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
Beware that the above docker-compose installation is a one time thing and keeping the version updated is a manual process (in contrast to docker and the first 2 installation options).