Creating The Perfect Software Development Environment: Day 06

Installing Development Tools

Now that we have a VM with a desktop installed, we can finally begin installing some development tools. The first one we will install is the Chromium web browser.

The Shell Provisioner

Packer has the notion of a provisioner which are different ways to install software into the image as it is being created. The simplest provisioner is the Shell Provisioner.

The shell Packer provisioner provisions machines built by Packer using shell scripts. Shell provisioning is the easiest way to get software installed and configured on a machine.

Essentially, any command you might type at the shell to install a tool can be used here. The trimmed down Xubuntu desktop does not come with a browser installed, so lets install one.


"provisioners": [
    {
        "type": "shell",
        "environment_vars": ["DEBIAN_FRONTEND=noninteractive"],
        "inline": ["sudo apt-get install --yes --install-suggests chromium-browser"]
    }
],
           
Chromium browser installed.
Chromium browser installed and working

As you can see, we are issuing the same command we might use at the terminal of a working machine. Add that section, rebuild your box and verify that Git got properly installed.

IntelliJ IDEA Installation via Snap

When installing IDEA by hand, I download the archive and unpack it somewhere. The folks over at Ubuntu Pit enumerate serveral installation options. The one that I find interesting is the Snap form. A Snap does for desktops what Docker does for servers: it isolates the application from other applications on the system, avoiding library version mismatches and other typical installation issues. The trade-off is that you have much less control over how the application is configured. For example, the IDEA Snap uses OpenJDK 8. What if you need to use Azul's Zulu JDK 10? Regardless, let's give the Snap method a spin and see how well it works with Packer.


"provisioners": [
    {
        "type": "shell",
        "environment_vars": ["DEBIAN_FRONTEND=noninteractive"],
        "inline": ["sudo apt-get install --yes --install-suggests git",
                   "sudo snap install intellij-idea-ultimate --classic"]
    }
],
            
Just IDEA.
IntelliJ IDEA installed and working

Multple IDE Installation via Snap

Now that we've seen how easy it is to install IDEs via Snap, let's make the environment polyglot, giving us the ability to develop in multiple programming languages.


"provisioners": [
    {
        "type": "shell",
        "environment_vars": ["DEBIAN_FRONTEND=noninteractive"],
        "inline": ["sudo apt-get install --yes --install-suggests git",
                   "sudo snap install clion --classic",
                   "sudo snap install datagrip --classic",
                   "sudo snap install goland --classic",
                   "sudo snap install intellij-idea-ultimate --classic",
                   "sudo snap install phpstorm --classic",
                   "sudo snap install pycharm-professional --classic",
                   "sudo snap install rubymine --classic",
                   "sudo snap install webstorm --classic"]
    }
],
            
Multiple IDEs installed.
Multiple IDEs installed and working

The Snap Store has lots of other tools you might be interested in installing, include Slack and Gimp.

Conclusion

Today we learned how to install software using the Shell Provisioner. We also learned how convenient it can be to install software using Ubuntu Snap. Next time, we'll use the Shell Provisioner to drive shell scripts to simplify installation tasks. We'll also experiment with Ubuntu Make, installing our IDEs that way.

Full Packer File


{
    "description": "Builds a Xubuntu 18.04 desktop box with various software development tools installed",
    "min_packer_version": "1.2.3",

    "variables": {
        "ssh_name"            : "vagrant",
        "ssh_pass"            : "vagrant",
        "virtualbox_appliance": "bionic-beaver.ova",
        "comment"             : "Test of Vagrant Cloud upload.",
        "cloud_user"          : "{{env `VAGRANT_CLOUD_ACCOUNT`}}",
        "cloud_token"         : "{{env `VAGRANT_CLOUD_TOKEN`}}"
    },

    "builders": [{
        "type"        : "virtualbox-ovf",
        "source_path" : "{{user `virtualbox_appliance`}}",
        "ssh_username": "{{user `ssh_name`}}",
        "ssh_password": "{{user `ssh_pass`}}",

        "boot_wait"           : "30s",
        "format"              : "ova",
        "guest_additions_mode": "disable",
        "headless"            : false,
        "keep_registered"     : false,
        "shutdown_command"    : "sudo shutdown --poweroff now",
        "shutdown_timeout"    : "2m",
        "skip_export"         : false,
        "output_directory"    : "output-virtualbox-ovf",
        "vboxmanage": [
		        ["modifyvm", "{{.Name}}", "--vram", "32"],
		        ["modifyvm", "{{.Name}}", "--memory", "2048"],
		        ["modifyvm", "{{.Name}}", "--cpus", "1"]
	      ],
        "vm_name"             : "packer-bionic-xubuntu"
    }],
    "provisioners": [
        {
            "type": "shell",
            "environment_vars": ["DEBIAN_FRONTEND=noninteractive"],
            "inline": ["sudo apt-get install --yes --install-suggests chromium-browser",
                       "sudo snap install clion --classic",
                       "sudo snap install datagrip --classic",
                       "sudo snap install goland --classic",
                       "sudo snap install intellij-idea-ultimate --classic",
                       "sudo snap install phpstorm --classic",
                       "sudo snap install pycharm-professional --classic",
                       "sudo snap install rubymine --classic",
                       "sudo snap install webstorm --classic"]
        }
    ],
    "post-processors": [
        [
            {
                "compression_level"  : 9,
                "keep_input_artifact": false,
                "output"             : "vagrant/bionic-xubuntu.box",
                "type"               : "vagrant"
            }
        ]
    ]
}