Vagrant

Vagrant is an open-source tool used for managing virtualized development environments. It simplifies the process of setting up, configuring, and managing virtual machines (VMs) by providing a consistent, repeatable, and portable environment.

Here’s how Vagrant works and some of its key features:

Key Concepts:

  • Vagrantfile: At the heart of a Vagrant environment is the Vagrantfile, a configuration file written in Ruby that defines the properties of the virtual machine (VM). It specifies things like the base image (called a "box"), networking, and other settings.

  • Boxes: These are pre-configured base images for virtual machines. Vagrant uses these to quickly set up environments. You can find boxes for different operating systems or configurations on Vagrant Cloud.

  • Providers: Vagrant uses "providers" to manage the virtual machines. The most common provider is VirtualBox, but Vagrant also supports other providers like VMware, Hyper-V, and Docker.

  • Provisioners: Vagrant can use "provisioners" like shell scripts, Chef, Puppet, and Ansible to automatically configure the machine after it has been booted.

Workflow:

  1. Initialize a Project: You start by creating a Vagrantfile with vagrant init, which generates a basic configuration file.

  2. Up: The vagrant up command brings up the VM. Vagrant checks the Vagrantfile for configuration settings, fetches the necessary box, and boots up the virtual machine.

  3. SSH Access: Once the VM is running, you can use vagrant ssh to SSH into the machine and work within that environment.

  4. Provisioning: If you have defined any provisioning scripts, they will run during the vagrant up process, or you can manually trigger them with vagrant provision.

  5. Suspend/Destroy: You can suspend the machine (vagrant suspend) to save its state or destroy it entirely (vagrant destroy) when you no longer need it.

Benefits:

  • Consistency: All developers on a project can share the same development environment, avoiding the "it works on my machine" problem.

  • Automation: Vagrant automates the setup and provisioning of environments, saving time and reducing manual setup errors.

  • Portability: A Vagrant environment can be easily shared with others, allowing the same environment to be used across different systems.


Example: Set up multiple VMs using Vagrant.
- Set up two (ubuntu) VMs in a private network and also install java11, maven, git in each VM using Vagrant.
- Using this setup two developers (two VMs) on a project share the same development environment, avoiding the "it works on my machine" problem.

Step 1: Install Vagrant and VirtualBox (or any other provider)

Step 2: Create a directory where your Vagrant configuration will reside

mkdir multi-vm-setup
cd multi-vm-setup

Step 3: Initialize Vagrant

vagrant init

It will create a basic Vagrantfile

Step 4: Modify the Vagrantfile to define multiple virtual machines

Vagrant.configure("2") do |config|
  # Define the first VM: Virtual Machine 1
  config.vm.define "vm1" do |vm1|
    vm1.vm.box = "ubuntu/bionic64"    # Base box for the vm1
    vm1.vm.hostname = "virtual-machine-1"    # Hostname
    vm1.vm.network "private_network", type: "dhcp" # Private network with DHCP
    vm1.vm.provider "virtualbox" do |vb|
      vb.memory = "1024"              # Allocate 1GB memory
    end
    
    # Install OpenJDK, Maven, and Git with a shell script in VM
    vm1.vm.provision "shell", inline: <<-SHELL
      sudo apt-get update
      # Install OpenJDK
      sudo apt-get install -y openjdk-11-jdk
      # Install Maven
      sudo apt-get install -y maven
      # Install Git
      sudo apt-get install -y git
    SHELL
  end
  
  # Define the first VM: Virtual Machine 2
  config.vm.define "vm2" do |vm2|
    vm2.vm.box = "ubuntu/bionic64"    # Base box for the vm2
    vm2.vm.hostname = "virtual-machine-2"    # Hostname
    vm2.vm.network "private_network", type: "dhcp" # Private network with DHCP
    vm2.vm.provider "virtualbox" do |vb|
      vb.memory = "1024"              # Allocate 1GB memory
    end
    
    # Install OpenJDK, Maven, and Git with a shell script in VM
    vm2.vm.provision "shell", inline: <<-SHELL
      sudo apt-get update
      # Install OpenJDK
      sudo apt-get install -y openjdk-11-jdk
      # Install Maven
      sudo apt-get install -y maven
      # Install Git
      sudo apt-get install -y git
    SHELL
  end

end 

Breakdown

  • config.vm.define "vm1" do |vm1|: Defines the VM with a box (ubuntu/bionic64), sets the hostname, and configures network settings.
  • vm1.vm.provider "virtualbox": Allocates memory for each VM.
  • You can add more VMs by repeating the config.vm.define block for additional machines.
  • Each VM is connected to the same private network via DHCP.

Step 5: Start all VMs

vagrant up

Step 6: Interact with a specific VM

vagrant ssh vm1   # Access the virtual machine 1
vagrant ssh vm2   # Access the virtual machine 2

Now, you’re inside the virtual machines and can start working in the development environment.

Step 7: Shut down all VMs

vagrant halt

Step 8: Destroy all VMs (if you want to remove them)

vagrant destroy


👉 I would prefer using any configuration management tool like Ansible (rather using Vagrant) to setup same development environments (e.g. same JDK version, Maven version etc) on multi VMs for the team.