Every developer has an array of different tools they need in order to complete their work. In my case, as a backend-developer and a student, my environment is changing with every new project that comes my way, be it a new internship, a tutoring job, or university work. It can be quite frustrating to have to rebuild or recreate my development environment over and over again, so I decided to automate it - not only to solve my problem, but also to gain experience in environment setups. Here's how it went down.
Setting up my dev environment
Whenever I start a new project, I generally have to download and install the tools I may need. This tends to take quite a bit of time to ensure the development environment will work seamlessly, because I generally have to:
- Find the software, which entails finding the website, and reading the installation instructions.
- Download it, or run the relevant commands that will download it.
- Install it.
- Ensure that it works to the project's specification by running a few trial commands.
- Customise it further (Only necessary for certain tools).
If this is done once or twice, it isn't so bad, but having to repeat this process every time becomes tedious and time consuming. Adding to this is the necessary customisation some tools need. For instance, I normally customise VS code to ensure that I have Wakatime, and other useful extensions.
Automating my dev environment
I found myself wasting too much of my time unnecessarily repeating these actions. That's why I looked into automation tools. I wanted something that worked consistently, made it easy to change things where needed, and saved those changes for the future. What I required was a one-stop shop that would install the necessary tools every time, on any machine, so that I could easily pick up where I left off.
My first step was to lay out a small list of tools I'd most likely need:
- Git, for version control.
- G++, to run C++ programs and also build any tools from source code.
- Python 3.5, to do python development.
- Java, for java development.
- VS Code, my go-to text editor.
What follows is my personal experiment comparing automation methods for my development environment. I looked into various methods of automation, namely:
- Docker: a containerisation software, that virtualises an operating system within a container.
- Chef: an automation tool for IT infrastructure.
- Codeanywhere: a cloud-based development environment tool.
- Ansible: another automation tool for IT infrastructure.
However, I ended up choosing Vagrant due to my past experience with it, and because it allows for easily separable environments.
Vagrant allows for the easy standardisation of development environments by offering simple and contained setup processes. It seemed perfectly suited for my automation quest, as it would allow me to have multiple environments for different projects or jobs, which are independent of one another. This suited my needs as I often run various projects at the same time, and Vagrant created the means to separate the customised environments easily, and switch between them with no further hassle. It can also run on most operating systems, creating a universal solution.
Here's how that works: Vagrant created a virtual machine (a.k.a. a Vagrantbox) on my computer that contains all the software and components I specified.
In order to create that Vagrantbox, I needed to:
- Create a Vagrantfile: This contains commands that tell Vagrant exactly how I wanted my box to be set up. There are a whole range of commands; for example, I could tell Vagrant to install specific software, or to run software installation scripts using the
provisioncommand. I used a basic Ubuntu Vagrantfile that I found in their documentation and then added provisioning commands that ran installation scripts.
- Run that file with Vagrant and, voila! My environment is set up.
Basically, this abstracted away all the nitty gritty processes involved in making sure I had exactly the right tools for a specific job. All the commands outlined in the Vagrantfile were run, and this installed all the tools I needed on a separate virtual instance that Vagrant had created.
Here is the Vagrantfile that installs all the software I needed:
Vagrantfile Vagrant.configure("2") do |config| config.vm.box = "ubuntu/xenial64" config.vm.provision:shell,path:'installer.sh',privileged:false config.vm.provision:shell,path:'install-pyenv.sh',privileged:true config.vm.provision:shell,path:'install-python.sh',args:'pyenv 2.7.15',privileged: true config.vm.provision:shell,path:'install-python.sh',args:'pyenv 3.6.5',privileged: true end
- It is simple to use, and easily customizable.
- It doesn't impact the machine, since all the tools are within a virtual machine.
- The environments can easily be shared because they can be recreated with the Vagrantfile on a different computer.
- It can be run across different platforms.
- It can be used in conjunction with version control systems (such as Github, etc.); this ensures that the most recent changes to the development environment are reflected in the Vagrantfile.
- Vagrant has no user interface. This means that if I needed to run a program that has any GUI components, I wouldn't be able to run it via a Vagrant based development environment. However, if I was running a web application, then I could forward the web app to my browser using the
networkcommands in the Vagrantfile.
- Vagrant runs in a virtual environment, so it is not necessarily comparable to a normal computer, in terms of processing capabilities. So, in situations where I want my applications to be performant, it is not useful.
These limitations turned out to be too much of a disadvantage for me because, at the time, I was working on a lot of projects that required GUI components.
I realised that I actually needed to install my tools on a physical Ubuntu machine, not a Vagrantbox. That's why I created a simple script that installs all the tools laid out above. This was surprisingly easy, and could definitely be expanded upon in the future if need be. Here's how I did that:
I wrote the script as a bash file. To do this I entered the same commands that I would normally use in a terminal to fetch and install software. To install git, for example, all I needed to do was run the command
apt-get install git. I could aggregate all the installation commands for the tools I wanted into the script, run it, and it installed all of them for me.
#!/bin/bash sudo apt-get update sudo apt-get upgrade -y sudo apt-get install -y g++ sudo apt-get install -y git git config --global user.email "email@example.com" git config --global user.name "Angus" chmod 777 install-pyenv.sh chmod 777 install-python.sh sudo ./install-pyenv.sh sudo ./install-python.sh `pyenv 2.7.15` sudo ./install-python.sh `pyenv 3.6.5` sudo apt-get install -y build-essential sudo apt install -y default-jdk sudo apt install -y curl curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg sudo install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/ sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list' sudo apt-get install -y apt-transport-https sudo apt-get update sudo apt-get install -y code code --install-extension ms-vscode.cpptools code --install-extension redhat.java code --install-extension yzhang.markdown-all-in-one code --install-extension ms-python.python code --install-extension wakatime.vscode-wakatime rm microsoft.gpg
Here's how that works: the script file fetches and installs the tools I need, and further sets up the tools that have Command Line Interfaces (CLIs). For instance, VS Code has a CLI and with it I could install extensions by using the
--install-extension command. This is great because it minimises the amount of time I had to spend going through the extension list and picking the ones I want.
- It's simple.
- It doesn't require a tooling setup.
- It can be used with other automation tools.
- It doesn't require tool-specific knowledge.
- This is only able to run on Linux distributions.
- It can only customize applications with CLIs.
Scripting the installation put other tools into perspective, as it was the most rudimentary way I could automate my development environment setup. While I will probably use Vagrant again in the future, scripting was better suited for me at the time. If you have better solutions, please feel free to message me.
Bogdan's i-vagrant - a great repository of useful vagrant installation scripts.
Vagrant's Documentation - super useful for any docker functionality.
Angus Mackenzie, a recent Computer Science graduate from the University of Cape Town, interested in everything tech. Likes puns, and his cat, Bernard.
Twitter handle: @AngusDeveloper
Github Profile: AngusTheMack