Vagrant is a way to build simply a virtual machine to fit your needs. It uses a system of template that you can build upon to match the requirements of your application.
Why would you want to run your project in a separate Virtual Machine?
Well there are multiple reason for that :
- Helps to keep your hosting machine clean from all the tools (ruby,python,gem,postfix,mailTrap,php versions … )
- Helps you to match the destination operation system (Develop on Mac and run on Ubuntu)
- Helps you to try without consequences on your system (Delete => rebuild)
- Share the same environment with all your team ! You build the same , execute the same way !
- Force you to make your environment reproductible and that helps a lot when you want to get a new machine running (DevOps Power !)
In order to create a virtual machine, Vagrant will use a configuration file to tell him what to do. This configuration file is pretty simple and looks like that:
Vagrant.configure do |config|
config.vm.hostname = "myproject.dev"
config.vm.box = "ubuntu/trusty"
config.vm.network :private_network, ip: "192.168.42.2"
config.vm.synced_folder "./", "/var/www/vm"
config.vm.synced_folder "../html", "/var/www/html"
config.vm.provider "virtualbox" do |v, override|
v.gui = false # Display the VirtualBox GUI when booting the machine
v.memory = 1024
v.cpus = 1
v.name = "my_dev_box"
Let’s explain the main parts of this file
- config.vm.hostname is simply the hostname of the virtual machine you will create
- config.vm.box is really important and is the template that you will be used for your virtual machine. Here we decide to use the template of an ubuntu machine. You can find a big catalog of templates here : https://atlas.hashicorp.com/boxes/search . Usually all you need is there but in case you need it you can actually build your own template for your projects using packer. I will present this in another article.
- config.vm.network is the private network that will be built to communicate with your machine ! You can create any subnet, if you’re not sure, verify your network settings but usually you can get away with it like me with 192.168.42.* or 192.168.99.*
- config.vm.synced_folder is for me the single most important parameter !!! It allows you to share one or multiple directory from your host (your physical machine) and the virtual machine you’re building. This means that if you edit the file on your physical machine using your favorite IDE, it will be updated at the same time on the virtual machine ! No deployment to do , all in real time! For web development i recommend you /var/www/html but you can choose whatever you’d like.
- config.vm.provider lets you override the default settings of the provider you are using. Here we downloaded VirtualBox to run the virtual machine but you could use something else as described here. You can for example override the virtualbox default settings for your machine to give it more CPU power. Too many “Out of Memory” errors? Alright, just increase the v.memory value! You can find all the options to set right here.
Once you have the base running you may want to add your own sauce to the machine: install what is missing, add your own configuration files, prepare the environment for your application.
This step is called provisioning, and it runs after the installation of the default template machine. There are several ways to provision your machine as described here. You can use bash scripts, Ansible , Chef etc…
My personal recommendation if you begin your journey to ops is to go with Ansible. For me it’s clean, simple , no special tricks to know and it runs out of the box with vagrant. There is a lot of documentation on Ansible and I will write an all article only about it in the near future.
For now all you need to know is that you can simply call Ansible recipes to do what you want by adding the following into your VagrantFile.
# Execute Ansible by guest OS to guest OS itself.
config.vm.provision :ansible_local do | ansible |
ansible.playbook = "playbook.yml"
ansible.install = true
ansible.version = "2.1"
ansible.provisioning_path = "/vagrant/ansible"
ansible.limit = "all"
Link to your application
Once you’ve established the base of your development machine (ideally it should be as close as possible to production one) you can insert your application onto the machine you created. There are several possibilities to do that:
- Create a shared folder between your host machine and your virtual machine. Basically when you update your file on your machine it will automatically be updated on the virtual machine since it s a shared folder ! That’s my favourite way and honestly the least painful. You can easily do that in your VagrantFile just by adding one line !
PHP1config.vm.synced_folder LOCAL_DIRECTORY, DIRECTORY_ON_VM
For example :
PHP1config.vm.synced_folder "../html", "/var/www/html"
- You can create a script to pull from your version control system onto your virtual machine every time you push something and do a real life deployment but onto the dev machine. Honestly for me it kills the benefits of having a dev machine to test things but the good thing is that it makes you test your deployment script !
Let’s go for a run !
Ok, now that we got the basics let’s talk about real life project. Usually I use a directory structure like this:
└── My Application
In my VagrantFile I add a shared folder between /html and /var/www/html in my virtual machine
I launch my IDE on the html directory and work as usual and see changes in real time on my virtual machine. The version control is also only set up only on the html directory.
To run my dev machine I go to the vm folder and simply do a
vagrant up to run my virtual machine.
Thanks to HashiCorp you can also share your dev environment via the command vagrant share so that people on the internet can also access your virtual machine (by default it’s only accessible from your machine)
To stop the virtual machine you just need to run the
vagrant halt. If you want to see all the commands vagrant allows you , simply type
Hope this article helped some of you , if you have questions don’t hesitate to post in the comments !