Dev Ubuntu 20.04: the history of a Virtual Machine managed as a Docker image
Tags: octograd2020
Published: 2020-05-26 05:41:55

First, what is it? This is a pre-configured Ubuntu 20.04 virtual machine that you can use for general development. With just a few steps you can have it up and running, ready to code, and adjusted to your needs.

But why? Why not install my own Ubuntu ISO in Virtual Box and do what it takes inside of it? And that's a good question. The answer is that you don't have a fully reproducible, disposable, shareable, and managed environment that way. And I know, that sounds a lot like how [Docker](https://www.docker.com/) images work in the containers world.

That was the main motivation: Docker with their `Dockerfile`s and how the images can be stored in a registry, ready to be used. Luckily, for the virtual machine world we have [Vagrant](https://www.vagrantup.com/), which aimed to solve the problem I was trying to solve: you can define a `Vagrantfile` and set some commands to run when you power up the machine. And then, you have the Vagrant Cloud, a place to store these machines.

So far so good, but then things started to become more interesting. Most of the base boxes (pre-built virtual machines you can use as a base in the `Vagrantfile`) didn't have a desktop installed. And looking at the official guides from Vagrant, they suggest we use [Packer](https://www.packer.io/), which can take a Linux ISO and start making modifications on top of. But it sounded too bare metal for my purpose, I just wanted to take an Ubuntu and apply some changes on it, the same way we do in Docker.

For solving that problem I first used [`bento/ubuntu-18.04`](https://app.vagrantup.com/bento/boxes/ubuntu-18.04) as the base box. It's kind of an official Ubuntu base box in the Vagrant Cloud, considering that the Canonical's one [had some blocking issues](https://github.com/hashicorp/vagrant/issues/9425#issuecomment-426114046). But later, when I switched to Ubuntu 20.04, I chose [`peru/ubuntu-20.04-desktop-amd64`](https://app.vagrantup.com/peru/boxes/ubuntu-20.04-desktop-amd64). It appeared to be a solid base box with desktop already installed. I even contributed to [opening an Issue](https://github.com/ruzickap/packer-templates/issues/92) in its [GitHub repository](https://github.com/ruzickap/packer-templates).

Then, I wanted to make it automatic. I wanted to do only the code part, such as adding a new tool in the virtual machine, and levering computers to build and release it for me. But there were two obstacles: I would need a CI that supports virtualization to run Vagrant and Virtual Box to build the machine. And I would also need a CI that supported a fake display, to run a simple test of the box after it's being built. Fortunately, [Travis](https://travis-ci.org/) has these two. I would be happy to use the awesome GitHub Actions and even contribute with some actions for the same purpose, but sadly, [it doesn't support nested virtualization](https://github.com/actions/virtual-environments/issues/183).

The next step was to manage the release cycle. For my luck, I met [`semantic-release`](https://github.com/semantic-release/semantic-release), a popular module to automate the releases in Node.js projects, relying on commit messages that follow a convention, and in my case, the [Conventional Commits](https://www.conventionalcommits.org/). I immediately fell in love with it and was excited to integrate into my project. I first had to [find a way on how to enforce Conventional Commits](https://github.com/felipecassiors/dev-ubuntu-20.04/pull/5) on my repository, and then, make `semantic-release` be able to push it to Vagrant Cloud.

I managed to convert my repository into an NPM based one, mainly due to its `package.json` since I would be using many NPM modules. But I was so happy with the result, that this even started a side project: a [Vagrant plugin for `semantic-release`](https://github.com/felipecassiors/semantic-release-vagrant), but still in an early development stage.

So now, if I want to add a new tool or new customization in the virtual machine, I just have to add the commands I want to a Bash script and commit to GitHub. After merging on the `master` branch, Travis automatically builds the virtual machine and then `semantic-release` deal with the bureaucracy of the versioning and releases for me.

It was also much-pleasant to receive the [first Issue the project](https://github.com/felipecassiors/dev-ubuntu-20.04/issues/4) from the community, which led me to create a brand new badge to display the sizes of any boxes in Vagrant Cloud. [And you can use it right now!](https://github.com/felipecassiors/vagrant-box-size/) See this preview: 
[![Vagrant box size](https://img.shields.io/endpoint?url=https://runkit.io/felipecassiors/vagrant-box-size/branches/master/bento/ubuntu-18.04/vmware_desktop)](https://app.vagrantup.com/bento/boxes/ubuntu-18.04)

I suggest you give it a try. Take a look at the [Get started](https://github.com/felipecassiors/dev-ubuntu-20.04#get-started) guide, it's simple. There are some tips for personal customizations, [such as my own](https://github.com/felipecassiors/my-dev-ubuntu-20.04).

And there are still plans for the future: 
- Continue the development of the Vagrant plugin for `semantic-release`, to help other people automate their releases without having to rely on complex Bash scripts.
- Create a [repository template](https://help.github.com/github/creating-cloning-and-archiving-repositories/creating-a-template-repository) to help other people scaffold their own fully managed virtual machine, which I think can be beneficial for development teams, that want to enforce the same environment efficiently.
- Somehow integrate with `dotfiles` repositories, and many other tricky adjustments to be made programmatically.


## Link to Code
{% github https://github.com/felipecassiors/dev-ubuntu-20.04 %}

## Download link
[Available on Vagrant Cloud](https://app.vagrantup.com/felipecassiors/boxes/dev-ubuntu-20.04)