Packer is an open source tool developed by Hashicorp for automating the creation of any type of machine image. You can use it for creating a custom Vagrant box for your development environment. That's what I will cover on this article.
Installation
You can get the installer for your operating system by going to packer.io/downloads. If you're on Linux you can get it from the repositories of some distributions.
Check the Install Packer section for installation instructions of some Linux distros including Ubuntu/Debian, Centos/RHEL, Fedora and Amazon Linux.
Note: If you get the following error on Debian when trying to add the Hashicorp repository, just install the package software-properties-common
.
sudo: apt-add-repository: command not found
$ sudo apt-get install -y software-properties-common
For Arch-based distributions, you can install Packer from the official repositories. Not to be confused with the packer
package available from AUR, this is an old package manager for Arch.
Vagrant boxes
Packer uses JSON and HCL templates for knowing the instructions to execute for building images. HCL is the format recommended for Packer 1.7 or later but still has support for JSON templates.
You must create an HCL or JSON file following the naming convention recommended by Packer, file_name.pkr.json
or file_name.pkr.hcl
.
Don't forget to create a directory for storing the configuration files for Packer and Vagrant.
$ mkdir virtual-environment
$ cd virtual-environment
JSON
Create a JSON file with the following content:
{
"provisioners": [
{
"type": "shell",
"execute_command": "echo 'vagrant' | {{.Vars}} sudo -S -E bash '{{.Path}}'",
"script": "scripts/setup.sh"
}
],
"builders": [
{
"communicator": "ssh",
"source_path": "ubuntu/focal64",
"provider": "virtualbox",
"add_force": true,
"type": "vagrant"
}
]
}
In the builders
section:
communicator
is set tossh
as Vagrant will access the virtual environment through an SSH connection.ubuntu/focal64
, assigned tosource_path
, is the base image that Packer will use during the building process.The provider that Vagrant will use is VirtualBox.
add_force
set to true is the same as using the--force
flag when running anyvagrant box
instruction.The builder type is set to
vagrant
for building a custom Vagrant box.
In the provisioners
section:
Vagrant has support for shell scripts, Ansible, Chef or Puppet as provisioners.
If you're using a shell script for provisioning your environment you have to define the following variables in this section.
type
set toshell
for using shell scripts.execute_command
is the instruction that Packer will run for provisioning the environment.The path of the script is set in the
script
variable.
HCL
If you're still using JSON templates, you can use the hcl2_upgrade
command for converting from JSON to HCL.
If you want to convert the file from the previous example, just run:
packer hcl2_upgrade -output-file=file_name.pkr.hcl file_name.pkr.json
The HCL template generated after running the above command will have the following content:
variable "version" {
type = string
default = ""
}
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
source "vagrant" "autogenerated_1" {
add_force = true
communicator = "ssh"
provider = "virtualbox"
source_path = "ubuntu/focal64"
}
build {
sources = ["source.vagrant.autogenerated_1"]
provisioner "shell" {
execute_command = "echo 'vagrant' | {{.Vars}} sudo -S -E bash '{{.Path}}'"
script = "scripts/setup.sh"
}
}
Provisioning
Create a directory named scripts
.
$ mkdir scripts
Inside the scripts
directory, create a shell script named setup.sh
that contains the instructions required for configuring the tools you need for your virtual environment.
You can use other provisioning tools like Ansible, Chef or Puppet but this time you will use a bash script.
For example, if you want to configure an environment for Python, your script will have the following content:
apt-get update
apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
xz-utils tk-dev libffi-dev liblzma-dev python-openssl git
su - vagrant -c "curl https://pyenv.run | bash
echo 'export PATH="$HOME/.pyenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3"
Instructions in your shell script will be executed by the root
user, that's why you don't need to run apt-get update
or apt-get install
with sudo
.
For configuring tools like Poetry and pyenv you need to run installation and configuration instructions with the vagrant
user, as this is the user you will log in with. In that case, run those instructions with su - vagrant -c
.
Building
Run packer build
after creating the template for Packer:
$ packer build file_name.pkr.json
$ packer build file_name.pkr.hcl
The above command will create a directory named output-vagrant
where you can find a package.box
file and a Vagrantfile
.
You need the package.box
file for configuring your virtual environment with Vagrant.
Configuring Vagrant
After creating the custom Vagrant box, you have to configure the virtual environment with Vagrant.
Create a Vagrantfile:
$ vagrant init dev-env
Where dev-env
is the value assigned to the config.vm.box
variable in the Vagrantfile. You can replace it according to your needs.
Add the package.box
file to Vagrant:
$ vagrant box add dev-env output-vagrant/package.box
Now your virtual environment is ready. You can initialize it and log in through SSH.
$ vagrant up
$ vagrant ssh
You're ready to go!
Top comments (0)