Loading...
Loading...
Marco Franssen

Large development teams often deal with the "It works on my machine" syndrome. One way to tackle this is to give every developer the same VM, ideally matching the production server. Imagine your company is building a web application hosted on a Debian server using Apache, MySQL, and PHP. With that setup in mind, I'll show you a simple example of scripting the build and provisioning of your machines. In this first part of the series, we'll focus on the packer.io builders.
First, let me explain what Packer is by quoting a few statements from its website.
Packer is a tool for creating identical machine images for multiple platforms from a single source configuration
Modern, Automated
Packer is easy to use and automates the creation of any type of machine image. It embraces modern configuration management by encouraging you to use automated scripts to install and configure the software within your Packer-made images. Packer brings machine images into the modern age, unlocking untapped potential and opening new opportunities.
Works Great With
Out of the box Packer comes with support to build images for Amazon EC2, DigitalOcean, VirtualBox, and VMware. Support for more platforms is on the way, and anyone can add new platforms via plugins.
To create an image for a specific platform, Packer uses builders. I don't want to dive into creating a builder plugin for your own platform or make you spend money to get your VM running, so I'll use the VirtualBox builder in this example. VirtualBox is free to use. If you don't already have it on your machine, please install VirtualBox before continuing. VirtualBox runs on Windows, Linux, and Mac, so you can follow along on any of these operating systems.
Please download the appropriate package for your operating system and architecture. Packer has packages for macOS, Linux, Windows, FreeBSD, and OpenBSD. Once you've installed Packer, we can create our script. First, create a folder on your machine called "my-first-packer-machine". In this folder, create a file called "packer-debian-x64-webserver.json". This JSON file defines our Packer script for building and provisioning the VM. Let's start by defining our VirtualBox builder.
{
"builders": [
{
"name": "debian64-webserver-vbox",
"type": "virtualbox-iso",
"guest_os_type": "Debian_64",
"guest_additions_mode": "disable",
"iso_url": "http://cdimage.debian.org/debian-cd/7.5.0/amd64/iso-cd/debian-7.5.0-amd64-netinst.iso",
"iso_checksum": "0a86e2fdef365f8bd626de7e754189291174b86a312c655fa6585eec3c6e5caa5e8f128e37a6989ae8d45743e158191d1b178d76bf338cb4512f0ee4aa9cda3c",
"iso_checksum_type": "sha512",
"ssh_username": "root",
"ssh_password": "r00tme",
"ssh_wait_timeout": "30m",
"shutdown_command": "echo 'packer' | shutdown -h now",
"vm_name": "my-webserver",
"format": "ova",
"hard_drive_interface": "sata",
"disk_size": 20000,
"vboxmanage": [
["modifyvm", "{{.Name}}", "--memory", "1024"],
["modifyvm", "{{.Name}}", "--cpus", "1"],
["modifyvm", "{{.Name}}", "--vram", "10"]
],
"boot_wait": "5s",
"boot_command": [
"auto url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/debian64.cfg "
],
"http_directory": "http"
}
]
}As you can see, we use the Debian ISO for "Wheezy", the latest stable release at the time of writing, to install our VM. The checksum is required so Packer can check the download's integrity. We configure our VirtualBox image with a 20 GB SATA hard disk. Don't worry: it is a dynamic disk, so it won't consume 20 GB immediately. We give the VM 1 GB of memory, one CPU, and 10 MB of video memory (the minimum requirement for VirtualBox Seamless Mode). The most important setting is boot_command, as this makes the Debian installation unattended. You can get an example Debian preseed file here. We'll create the file debian64-webserver.cfg in a subfolder…
If you want to use another OS, you can use VBoxManage from your command line to find out which guest OS types are supported.
VBoxManage list ostypes### Localization
d-i debian-installer/locale string en_US
d-i debian-installer/language string en
d-i debian-installer/country string US
d-i debian-installer/locale string en_US.UTF-8
d-i localechooser/supported-locales multiselect en_US.UTF-8
# Keyboard selection.
d-i console-tools/archs select at
d-i console-keymaps-at/keymap select us
d-i keyboard-configuration/xkb-keymap select us
### Network configuration
d-i netcfg/choose_interface select auto
d-i netcfg/get_hostname string debian-wheezy
d-i netcfg/hostname string debian-wheezy
d-i netcfg/wireless_wep string
d-i hw-detect/load_firmware boolean true
### Mirror settings
d-i mirror/country string manual
d-i mirror/http/hostname string http.debian.net
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string
d-i mirror/suite string wheezy
### Account setup
### Root
d-i passwd/root-password password r00tme
d-i passwd/root-password-again password r00tme
d-i passwd/make-user boolean false
### Clock and time zone setup
d-i clock-setup/utc boolean true
d-i time/zone string GMT+1
d-i clock-setup/ntp boolean true
### Partitioning
d-i partman-auto/disk string /dev/sda
d-i partman-auto/method string regular
d-i partman-auto/choose_recipe select atomic
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman/mount_style select uuid
### Apt setup
d-i apt-setup/non-free boolean true
d-i apt-setup/contrib boolean true
d-i apt-setup/services-select multiselect security, volatile
d-i apt-setup/security_host string security.debian.org
d-i apt-setup/volatile_host string volatile.debian.org
### Package selection
tasksel tasksel/first multiselect
d-i pkgsel/include string openssh-server build-essential nfs-common ssh ca-certificates curl linux-headers-amd64 apache2 php5 php5-mysql mysql-server-5.5 mysql-client samba vim
mysql-server-5.5 mysql-server/root_password password r00tmysql
mysql-server-5.5 mysql-server/root_password_again password r00tmysql
d-i pkgsel/upgrade select safe-upgrade
popularity-contest popularity-contest/participate boolean false
### GRUB
d-i grub-installer/only_debian boolean true
### Finishing up the installation
d-i finish-install/keep-consoles boolean true
d-i finish-install/reboot_in_progress noteAs you can see, we make sure the Debian installation uses the right time zone and has the right packages installed. I also choose to install Samba so we can have a shared folder accessible from our host, and Vim so we have a decent text editor for changing configuration files such as php.ini. Feel free to add any PHP packages you need (php5-memcache, for example) to the di pkgsel/include string line.
Now we're ready to try our packer.io script. First, open a shell or, on Windows, your command prompt, and navigate to your my-first-packer-machine folder. In this folder, we can execute the following Packer commands.
# validates your packer template file
packer validate packer-debian-x64-webserver.json
# take the template and actually run the builds within it,
# producing any resulting machine images.
packer build packer-debian-x64-webserver.jsonThe first command validates your JSON file; the second runs the builds specified in your Packer template. If you have multiple builders and only want to run one, use the -only=debian64-webserver-vbox command-line parameter to select the builder with that name. Packer caches the Debian ISO in the packer_cache folder, so it won't have to download it again when you rerun the build. Keep these files, as you'll need them for the next part of the series. The result should be a my-webserver.ova file of about 700 MB. By double-clicking this file, you can import the VirtualBox appliance and start using your VM.
Next week, in the second part, we'll look at Packer variables and provisioners to further automate our machine builds.
Marco Franssen
Use Gulp.js to automate PHP linting, PHPUnit tests, coding standards, documentation, and static analysis, with watch tasks for immediate feedback.
Marco Franssen
Customize a Debian VirtualBox VM with Packer user variables, file uploads, and shell provisioners in this 2014 tutorial covering MySQL and Apache setup.
Marco Franssen
Write synchronous and asynchronous Node.js tests with Mocha, Chai assertions and Sinon spies, stubs and fake timers, then run them with Grunt.
Marco Franssen
Automate development and CI tasks with Grunt: configure a Gruntfile, run task targets, combine tasks, and watch files to rerun jobs when they change.