Post summary: How to run multiple machines on Vagrant described in a single Vagrantfile.
The code below can be found in GitHub sample-dropwizard-rest-stub repository in Vagrantfile file. This post is part of Vagrant series. All of other Vagrant related posts, as well as more theoretical information what is Vagrant and why to use it, can be found in What is Vagrant and why to use it post.
Vagrantfile
As described in Vagrant introduction post all configurations are done in a single text file called Vagrantfile. Below is a Vagrant file which can be used to initialize two machines. One is same as described in Run Dropwizard Java application on Vagrant post, the other is the one described in Run Docker container on Vagrant post.
Vagrant.configure('2') do |config|
config.vm.hostname = 'dropwizard'
config.vm.box = 'opscode-centos-7.2'
config.vm.box_url = 'http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-7.2_chef-provisionerless.box'
config.vm.synced_folder './', '/vagrant'
config.vm.define 'jar' do |jar|
jar.vm.network :forwarded_port, guest: 9000, host: 9100
jar.vm.network :forwarded_port, guest: 9001, host: 9101
jar.vm.provider :virtualbox do |vb|
vb.name = 'dropwizard-rest-stub-jar'
end
jar.vm.provision :shell do |shell|
shell.inline = <<-SHELL
sudo service dropwizard stop
sudo yum -y install java
sudo mkdir -p /var/dropwizard-rest-stub
sudo mkdir -p /var/dropwizard-rest-stub/logs
sudo cp /vagrant/target/sample-dropwizard-rest-stub-1.0-SNAPSHOT.jar /var/dropwizard-rest-stub/dropwizard-rest-stub.jar
sudo cp /vagrant/config-vagrant.yml /var/dropwizard-rest-stub/config.yml
sudo cp /vagrant/linux_service_file /etc/init.d/dropwizard
# Replace CR+LF with LF because of Windows
sudo sed -i -e 's/\r//g' /etc/init.d/dropwizard
sudo chmod +x /etc/init.d/dropwizard
sudo service dropwizard start
SHELL
end
end
config.vm.define 'docker' do |docker|
docker.vm.network :forwarded_port, guest: 9000, host: 9000
docker.vm.network :forwarded_port, guest: 9001, host: 9001
docker.vm.provider :virtualbox do |vb|
vb.name = 'dropwizard-rest-stub-docker'
vb.customize ['modifyvm', :id, '--memory', '768', '--cpus', '2']
end
docker.vm.provision :shell do |shell|
shell.inline = <<-SHELL
sudo yum -y install epel-release
sudo yum -y install python-pip
sudo pip install --upgrade pip
sudo pip install six==1.4
sudo pip install docker-py
SHELL
end
docker.vm.provision :docker do |docker|
docker.build_image '/vagrant/.', args: '-t dropwizard-rest-stub'
docker.run 'dropwizard-rest-stub', args: '-it -p 9000:9000 -p 9001:9001 -e ENV_VARIABLE_VERSION=1.1.1'
end
end
end
Vagrantfile explanation
The file starts with a Vagrant.configure(‘2’) do |config| which states that version 2 of Vagrant API will be used and defines constant with name config to be used below. Guest operating system hostname is set to config.vm.hostname. If you use vagrant-hostsupdater plugin it will add it to your hosts file and you can access it from a browser in case you are developing web applications. With config.vm.box you define which would be the guest operating system. Vagrant maintains config.vm.box = “hashicorp/precise64” which is Ubuntu 12.04 (32 and 64-bit), they also recommend to use Bento’s boxes, but I found issues with Vagrant’s as well as Bento’s boxes so I’ve decided to use one I know is working. I specify where it is located with config.vm.box_url. It is It is CentOS 7.2. With config.vm.synced_folder command, you specify that Vagrantfile location folder is shared as /vagrant/ in the guest operating system. This makes it easy to transfer files between guest and host operating systems. Now comes the part where two different machines are defined. First one is defined with config.vm.define ‘jar’ do |jar|, which declares variable jar to be used later in configurations. All other configurations are well described in Run Dropwizard Java application on Vagrant post. The specific part here is port mapping. In order to avoid port collision port 9000 from the guest is mapped to port 9100 to host with jar.vm.network :forwarded_port, guest: 9000, host: 9100 line. This is because the second machine uses port 9000 from the host. The second machine is defined in config.vm.define ‘docker’ do |docker|, which declares variable docker to be used in further configurations. All other configurations are described in Run Docker container on Vagrant post.
Running Vagrant
Command to start Vagrant machine is: vagrant up. Then in order to invoke provisioning section with actual deployment, you have to call: vagrant provision. All can be done in one step: vagrant up –provision. To shut down the machine use vagrant halt. To delete machine: vagrant destroy.
Conclusion
It is very easy to create Vagrantfile that builds and runs several machines with different applications. It possible to make those machine communicate with each other, hence simulation real environment. Once created file can be reused by all team members. It is executed over and over again making provisioning extremely easy.