Should you containerize legacy applications? And can you really do it effectively?
The answer to both questions is yes. Even if you have an application that was not originally designed to run inside a container, its possible to deploy it using a platform like Docker. And the effort required to do so is often well worth it.
In this post, we'll take a look at basic strategies for moving legacy apps into containers. Well also discuss which type of containerization strategy is likely to be best for your legacy apps, as well as what makes a legacy app suitable or unsuitable for containerization.
Why run legacy apps inside a container?
First, though, lets make clear why you would want to containerize a legacy app.
Legacy apps can remain useful for years or even decades after their initial release. An older application may have a large and well-established user base, willing to pay for support and updates indefinitely, rather than adjust to new software. The useful lifetime of an application may be considerably longer than that of the platform on which it was originally developed or delivered.
If you have such an app, it makes sense to adapt it to current infrastructure platforms (such as containers) when possible. Thats more efficient than rewriting the entire application each time a new type of infrastructure becomes available.
Containerising legacy applications can also add much needed speed and agility to applications that still need to be changed.
The clean approach to containerization
If you are containerising a legacy app, there are two general approaches you can takeone clean and the other dirty. Well discuss the clean strategy first before moving onto the dirty approach.
Keeping it Clean
What makes the clean strategy for containerizing legacy apps clean in the first place? More than anything, it's about containerizing the app in such a way that you maintain the basic philosophy of containerization and microservices.
Most legacy apps in their original states are far from being microservice-oriented. Most well-designed container-based apps, on the other hand, are embodiments of microservice architecture. To containerize a legacy app the clean way, you must refactor it so that it is modular and can be inserted into a microservice architecture.
What's the best way to refactor a legacy app? There are times when the approach to refactoring will be suggested by the existing architecture of the app itself, and there are times when the nature and requirements of the app will impose design constraints which might not be present in a designed-from-scratch container app. But for the most part, you'll be faced with a few basic choices. They include:
In practice, of course, you are likely to use a combination of each of these strategies in refactoring a typical legacy app. Functional boundaries, resource boundaries, and data boundaries often coincide to one degree or another, and sets of functions often interact with a limited set of resources. As you come to recognise these patterns of interaction, the natural boundaries that can be used to define microservices become more apparent.
This kind of refactoring takes time and effort, but the result is likely to be something very close to a native container app, which takes full advantage of the container system's features.
The dirty approach
What about the not-so-clean strategy for containerizing a legacy app?
Dirty containerization consists basically of taking the entire legacy app and stuffing it into a container, making the necessary adjustments required for it to operate in a container environment. An app that is containerized in this way can leverage some container features (those involving networking and system resources, for example), but without a full redesign, it wont be a microservices-based app.
The resulting containerized app is likely to be bloated and not optimised to run as a container. Still, it will allow the application to run on next-generation containerized infrastructure, and allow us to secure the other benefits of Docker such as simplified deployments, consistent environments, and better resource consumption of infrastructure.
Needless to say, with legacy apps, this clean/dirty distinction may not always be so clear. It may be easier to refactor partially (in other words, to move some functions out to microservices, but keep large chunks of the original code intact). When this happens, the result may not be elegant in terms of containerization standards or microservices architecture, but it may make good use of most container features without requiring a level of refactoring effort that can't be justified by the value of the software.
And sometimes you just dont...
And there are those legacy apps which are simply not suitable for containerization, either of the clean or dirty kind. This includes apps written in outdated programming languages (RPG and FORTRAN IV are happy at the retirement home, and don't need to be bothered with containerization, for instance).
Other apps that depend on resourcessuch as obsolete or arcane hardware, non-standard databases, or specialised peripheralsmay not lend themselves well to containerization. In these cases, you would be better served by rewriting the app in a modern, container-friendly framework instead of trying to squeeze it into a container just to make it run on containerized infrastructure.
So, should you containerize legacy apps? Yes, as long as you understand what you're doing, why you're doing it, and what the limitations of the process are. You can teach old apps new tricks. And in those cases when a legacy app isn't up to learning new tricks, you can keep its existing user base happy by adapting the app so that users can deploy it via a container. The result may fall far short of being as elegant as a native container app, but more often than not, it's worth the effort.