Dec 5, 2024 by Zacharia Mansouri | 399 views
https://cylab.be/blog/368/multipass-vs-vagrant-for-creating-docker-ready-vms
When it comes to managing Virtual Machines that run Docker images, developers often face a choice between various tools for VM creation. Two popular options, Vagrant and Multipass, offer distinct approaches, each with its own strengths and limitations. Multipass, designed by Canonical, is focused on simplicity and lightweight VM management, making it a strong choice for quick deployments. On the other hand, Vagrant, widely used for development environments, is highly customizable and integrates well with various provisioning tools.
In this blog post, we’ll compare how to automate the deployment of Docker containers inside VMs using both these technologies, which can be useful for situations such as when you need:
We’ll dive into a side-by-side comparison of Multipass and Vagrant, analyzing their capabilities for creating VMs that run Docker images. Whether you’re looking for flexibility or speed, this guide will help you decide which tool best suits your workflow.
Multipass is a tool to get an instant Ubuntu VM with a single command since it can launch and run virtual machines and configure them with cloud-init. As stated on the Canonical official website, its installation can be achieved as follows:
sudo snap install multipass
Vagrant is described as a command line utility for managing the lifecycle of VMs by isolating dependencies and their configuration within a single disposable and consistent environment.The installation of Vagrant requires more steps. The Hashicorp documentation has a page dedicated to its installation.
The Docker container to deploy is a basic nginx
server. We’ll see how to deploy it in a VM using Multipass and Vagrant.
The following structure includes a launch.sh
script, used to initiate the overall setup process. Inside the 2transfer/
directory, there is an install.sh
script, which contains the VM configuration and creation commands, and a project/
directory that uses the docker-compose.yml
file within it to deploy the nginx
server. In short, launch.sh
orchestrates the transfer of files and execution of install.sh
inside the VM, which then handles the setup and deployment of the Docker project.
|____launch.sh
|____2transfer/
|____install.sh
|____project/
|____docker-compose.yml
The launch.sh
script automates the creation and setup of a Multipass VM named my-vm
. It first launches the VM with 2 CPUs, 2 GB of memory, and a 10 GB disk. Then, it transfers all files and directories from the 2transfer/
folder to the VM. Afterward, it executes the install.sh
script inside the VM to handle the deployment of the nginx
server.
launch.sh
#!/bin/bash
multipass launch -n my-vm --cpus 2 --memory 2G --disk 10G
multipass transfer -r 2transfer/* my-vm:.
multipass exec my-vm install.sh
The install.sh
script configures a system to use Docker and Docker Compose. It updates the package list and installs Docker, enabling and starting its service. It adds the current user to the docker
group for permission to run Docker commands. Next, it installs Docker Compose, verifies both installations, and navigates to the project
directory to build and deploy the Docker Compose project in detached mode.
2transfer/install.sh
#!/bin/bash
# Update package list
sudo apt update
# Install Docker
sudo apt install -y docker.io
# Enable and start Docker service
sudo systemctl enable docker
sudo systemctl start docker
# Add the current user to the docker group
sudo usermod -aG docker $USER
# Install Docker Compose
sudo apt install -y docker-compose
# Check Docker and Docker Compose versions
sudo docker --version
sudo docker-compose --version
# Navigate to the project directory and start the Docker Compose project
cd project && sudo docker-compose up --build -d
As previously stated, the Docker project is a simple nginx
server.
2transfer/project/docker-compose.yml
version: '3'
services:
web:
image: nginx:latest
ports:
- "8080:80"
Executing ./launch.sh
will automate the creation of a Multipass virtual machine, transfer necessary files to it, execute the setup script (install.sh
) to configure the VM and deploy the Docker Compose project.
./launch.sh
|____Vagrantfile
|____project/
|____docker-compose.yml
This structure contains a Vagrantfile
for configuring and provisioning a VirtualBox VM using Vagrant, and a project/
directory containing a docker-compose.yml
file. The Vagrantfile
sets up the VM and provisions it to use the docker-compose.yml
file within the project/
directory to deploy the nginx
server.
The Vagrantfile
sets up a VirtualBox VM named my-vm
with 2 GB of RAM, 2 CPUs, and Ubuntu 20.04 as the base OS. It disables the default synced folder, shares the project
directory, and forwards port 8081. The VM is provisioned using a shell script that updates the system, installs Docker and Docker Compose, enables Docker, and deploys a Docker Compose project from the shared folder. This configuration automates the setup of a development environment for Docker-based projects.
Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/focal64"
config.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
vb.cpus = "2"
vb.name = "my-vm"
end
config.vm.synced_folder ".", "/vagrant", disabled: true
config.vm.synced_folder "project", "/vagrant/project"
config.vm.network "forwarded_port", guest: "8081", host: "8081"
config.vm.provision "shell", keep_color: true, inline: <<-SHELL
mkdir /home/vagrant/project
cp -r /vagrant/project/* /home/vagrant/project
# Update
sudo apt-get update
# Install dependencies
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
# Add Docker GPG key and Docker repo
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
# Install Docker
sudo apt-get install -y docker-ce
# Add vagrant user to docker group
sudo usermod -aG docker vagrant
# Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Verify Docker Compose installation
docker-compose --version
# Start Docker
sudo systemctl enable docker
sudo systemctl start docker
# Deploy and run docker containers
cd /home/vagrant/project
docker-compose up --build -d
SHELL
end
Once again, as previously stated, the Docker project is a simple nginx
server.
project/docker-compose.yml
version: '3'
services:
web:
image: nginx:latest
ports:
- "8080:80"
With a single command, Vagrant will create and configure the VM as specified in the Vagrantfile
, automatically provisioning it to deploy the nginx
server:
vagrant up
vagrant up
Error: No Usable Default Provider FoundThe error occurs because installing Multipass enables KVM, which conflicts with VirtualBox. This issue was resolved by ensuring VirtualBox’s kernel modules were correctly installed and configured. Follow these steps to fix it:
Verify VirtualBox installation:
VBoxManage --version
If it returns an error, proceed with the following steps.
Update the system:
sudo apt update
sudo apt upgrade
Install required kernel headers and modules:
sudo apt install linux-headers-generic
sudo apt install linux-headers-$(uname -r)
sudo apt install virtualbox-dkms
Reconfigure VirtualBox kernel modules:
sudo dpkg-reconfigure virtualbox-dkms
sudo modprobe vboxdrv
Restart and check VirtualBox service:
sudo systemctl restart virtualbox.service
sudo systemctl status virtualbox.service
Verify VirtualBox is working:
VBoxManage --version
This should now return the version successfully.
If you use VirtualBox as a provider for Vagrant instead of KVM, you need to adjust kernel modules due to conflicts between KVM and VirtualBox, since Multipass uses KVM (libvirt).
To switch from VirtualBox to Multipass, stop all VirtualBox VMs, then enable KVM:
sudo modprobe kvm
sudo modprobe kvm_intel
To switch from Multipass to VirtualBox: stop all Multipass VMs, then remove KVM modules:
sudo rmmod kvm_intel
sudo rmmod kvm
When choosing between Multipass and Vagrant, your decision largely depends on your project’s complexity and your need for customization.
Multipass stands out for its simplicity and lightweight nature. Designed to quickly run Ubuntu VMs, it requires minimal configuration, making it ideal for straightforward tasks like installing software such as Docker. Its commands are intuitive, and it integrates seamlessly with Ubuntu, since it’s a product of Canonical. This makes Multipass perfect for developers seeking a fast way to set up a VM.
On the other hand, Vagrant offers much greater flexibility and power, particularly for more complex setups. With a robust ecosystem of OS images (called “boxes”) and support for multi-VM configurations, it’s built for replicating environments consistently. Whether you’re provisioning with tools like Ansible or working across various providers like VirtualBox and Docker, Vagrant gives you fine-grained control. While its initial setup can be more complex, its extensive capabilities make it worth the effort for more demanding projects.
Multipass is optimized for Ubuntu and uses the native hypervisor on your host system (such as KVM on Linux), eliminating the need for additional hypervisors like VirtualBox. This makes it efficient and lightweight, particularly if you’re deploying to Ubuntu servers in production.
Vagrant, depending on the provider you use, can be heavier. For instance, VirtualBox-based configurations can consume more resources. However, Vagrant’s Docker provider allows you to bypass full VMs entirely by running containers, potentially delivering better performance for containerized workflows.
Multipass takes a minimalist approach, offering limited provisioning options. You can configure instances via bash scripts or by SSHing into them, but it’s less suited for complex automation or for environments beyond Ubuntu.
In contrast, Vagrant supports detailed provisioning scripts directly in the Vagrantfile, whether you’re using shell scripts or advanced tools like Ansible. Vagrant is also compatible with a wider variety of operating systems and hypervisors, making it a powerful choice for automating multi-OS or multi-VM setups.
Multipass doesn’t have built-in Docker integration, though Docker can be manually installed on the VM. This works well for basic use cases, like running Docker Compose, but lacks the deeper integration or automation that some workflows may require.
Even though we do not show it in this blog post, Vagrant, however, provides native Docker support. You can use Vagrant to manage Docker containers without needing a full VM. Its Docker Compose provider is particularly useful for orchestrating containers alongside other VMs, making it an excellent option for hybrid setups.
If simplicity is your priority, Multipass is a great choice. It’s tailored for Ubuntu environments and quick-start scenarios but lacks the customization options of Vagrant.
Vagrant, on the other hand, is extremely versatile. Whether you’re managing multiple VMs, integrating complex provisioning tools, or combining VM and container workflows, Vagrant gives you the control you need to handle sophisticated infrastructure setups.
Multipass is ideal for lightweight, Ubuntu-focused tasks. If you need a quick and efficient way to spin up a single VM for Docker or other simple software installations, Multipass provides a smooth and streamlined experience. Vagrant is the tool for more demanding projects requiring flexibility and automation. Whether you’re managing diverse OS environments, writing detailed provisioning scripts, or coordinating multi-VM setups, Vagrant shines in its ability to replicate complex environments across teams and machines. Choosing between Multipass and Vagrant therefore depends on the level of precision and the scale of the project you’re working on.
This blog post is licensed under CC BY-SA 4.0