I love portability. I dual boot Windows and macOS on my home machine. I rent VPSs running various versions of Debian, Ubuntu and CentOS. As such, the majority of the software I write is in Go because of the portability it offers.
As the amount of software Course Trakr required grew, I ran into bottleneck in my development process. Depending on my mood and phase of the moon, my development environment may be either Windows or macOS and production and staging environment could be a server running Ubuntu 14.04 or Debian 8. Everything from building the software to monitoring it was a mess. Granted, this is a problem I created myself.
Adding, removing and configuring services was difficult. Different OS use different init systems e.g. systemd, sysvinit, upstart. To save myself from the headache of learning the ins and outs of each of them, I used runit instead. Secrets and configuration details were baked into the binaries which further, blurred the lines between my development and production environments.
Deploying software remotely involved running a script to pull from a private git repo, building the source then restarting the services. A failure in this process could leave some services in a half running state. I lacked the ability to properly monitor each service because the overhead of manually configuring a cross product of environments and services was insane.
Monitoring is a pain, partly because I always feel like I'm simultaneously logging too much and not enough. Some services were cannibalizing CPU and memory or performed better or worse depending on the number of CPU cores the machine. Debugging binaries running remotely needed be easy and my setup killed my development productivity.
I began looking for a solution upon realizing these problems will be multiplied when scaling. There are solutions and as it turns out, there is an entire career to be made from solving this class of problems. A bit of research of lead me to believe that containers would solve many of the problems I had.
Here's Amazon's definition of what containers are:
Containers allow you to easily package an application's code, configurations, and dependencies into easy to use building blocks that deliver environmental consistency, operational efficiency, developer productivity, and version control. Containers can help ensure that applications deploy quickly, reliably, and consistently regardless of deployment environment. Containers also give you more granular control over resources giving your infrastructure improved efficiency.
In fell swoop all my problems had solutions. Creating an environment that was consistent across development and production was now possible. It's amazing to me that with a single command, I could simultaneously run two different versions of PostgreSQL on a single machine without one affecting the other. Not that I would ever need to, but I could if I wanted to. I was now in portability heaven.