Untangling Dependencies
Software dependencies can be a tangled mess. However much progress has happened in the space of managing them using virtual machines and containers.
When developing in a language like Java, one used to have to explicitly download and reference 3rd party jars and their dependencies, or their build would not work or be incomplete. Thanks to package managers like Maven and Gradle, this is a thing of the past. Simply add an entry to your pom.xml and all of your dependencies are automatically resolved, downloaded, and included in your build.
Similar benefits have been realized by Linux systems administrators who use, for example, yum on their CentOS installations to install or update software packages on their machines. With one sweeping ‘yum update’, everything is taken care of for you.
Multipurpose Servers
Starting our company, we naturally wanted to get the most out of the equipment we invested in. Our web server not only served up multiple apps, but it was also our database server, our VPN server, our trouble ticketing system, our firewall, and so on. And why not? None of these apps were individually getting enough traffic to warrant the cost and complexity of each running on a dedicated machine. It served us well for a long time.
However each app has its own dependencies. Over time, those apps will require updates, and those updates may have different dependency requirements. You see where this is going. Take this scenario: until today, apps A and B have required PHP version 5.3. The next version of app A requires PHP 5.4 — but how will this affect your other apps that also depend on PHP ?
Best case, app B already supports 5.4 and should not be affected. However to be certain, you will probably want to perform some regression testing. And what about apps C, D, and E ?
Worst case, app B (or C, or D…) does not yet officially support PHP 5.4. You are now in a situation where you have to make some tough decisions. Some options are:
- Upgrade app a and PHP and hope for the best. Note: hope is not a recommended change control strategy.
- Do not upgrade app A until other apps deem it’s safe to run on PHP 5.4. You could be holding off for a long time, forgoing features and security updates during that period.
- Try to run multiple versions of PHP on a single machine (or VM), one per app. A hack at best.
Container Options
One way to address this issue is by using virtual machines. This can be using VMware, or by using cloud computing like Amazon EC2. The benefit of this is that it would enable you to build completely separate operating systems, and update each one independently as you see fit for the applications that run on them. Downsides include having to separately patch and manage each virtual instance, and the additional system resources that they consume.
Another way of achieving the same end, but without all of the overhead with a complete OS install on a VM, is to utilize a virtual environment (“VE’s”) like Docker or Vagrant. Here is an article touting the benefits of VE’s versus VMs, and comparing these variants. Another article shows how you can use Docker images to run multiple PHP variants. A feature of the container approach is that you can still continue to use other local system resources, for example, a mysql database or a filesystem.
Other Benefits
In addition to dependency management, another benefit that can be realized with containers is streamlining change management within your DevOps processes. While it’s true that modern programming languages now have package managers to bundle up dependencies needed by your code, there are often environmental dependencies that come into play. For example, application server versions (Tomcat, PHP, etc) and their included libraries, databases, command-line utilities, configuration files, and so on. Envision your nightly build not only compiling and testing your source code, but creating an immutable, portable image, complete with executable code and all dependencies. This can then be stored in your repository and deployed to your development, QA, and production environments. Refer to this example use case, using GitHub, Jenkins and Docker.
Conclusion
Dependency management can be complex and riddled with landmines. A single server or virtual machine hosting multiple applications can be a quick and cost effective way to get running. However in the long run, migrating apps to their own virtual machines (VMs) or virtual environments (VEs) will provide have the most flexibility and consistency with regard to dependencies in your software stack.
