Should I containerize my cloud app?
I just got back from Microsoft Ignite the Tour London, where I spent most of my time talking with attendees about the various ways you can run containers in Azure.
Many people I spoke to were already on the journey to containerizing their apps and some were already using Kubernetes. But there were also a lot of people who were very new to the concepts of Docker and Kubernetes and were simply interested in finding out whether they needed to containerize, and what the best way to run those containers on Azure is.
So in this post, I want to summarize some of my thoughts on whether you should consider containerizing your Azure applications.
What are your pain points?
The first, and most important question, is "what are your pain points"? Docker and Kubernetes offer solutions to many common problems, but if you don't have those problems, then you may not need to transition to containers at the moment.
To determine if containers would bring value to your scenario, consider questions like is it difficult to build my application? Maybe your app requires a lot of custom SDKs and tools to be installed on developer and build machines. If so, containerizing the build environment with techniques like multi-stage builds can be a great way to simplify building the code and ensuring that you get consistent output.
Is it difficult to run my application locally? Many cloud applications can pose a real problem for development teams who need to run multiple services - maybe several microservices, and other third party applications like RabbitMQ or Elasticsearch, just to be able to test the application locally. By containerizing your application, you can make it much simpler to run locally, by defining a simple Docker compose file
Is it difficult to deploy my application? Does deploying your application involve running complex setup scripts to get a Virtual Machine set up in just the right way to be able to run the app? Even if you've automated that with tools like Puppet or Chef, containerization often proves to be a much simpler solution to ensuring that your application's dependencies are met, and gives you greater flexibility to where you run that application.
Is it difficult to orchestrate my application? If you have built a microservices application, then that brings a whole host of new challenges. All the microservices need to be able to communicate with each other, you want to be able to monitor their health, to scale them independently, and perform more advanced deployment patterns like blue-green swaps or rolling upgrades. Rolling your own solutions to these problems is complex and error-prone, which is why container orchestration platforms like Kubernetes have become so popular in recent years - they provide solutions to many of the operational challenges that microservices bring.
Is it difficult to modernize my application? I had quite a lot of people asking me whether they should rewrite their .NET Framework apps in .NET Core or just containerize them? My answer was that containerizing them would very likely be much quicker. Of course the resulting containers would be Windows containers which places some constraints on what services they can run on, but one of the great benefits of containerization is that once you've taken the trouble to create a Dockerfile for your legacy app (which ordinarily shouldn't take more than a day or two), you've opened the door to all the other benefits that containers offer.
My app is running in a VM
If your application is currently running in a Virtual Machine in Azure, then there are a couple of ways in which containerization might help you. The first we've already mentioned - it removes the need for any pre-requisites other than Docker itself to be installed on the host machine. So all the complexity of configuring a special snowflake VM that knows how to run your app is taken away, and it can now run on any VM with Docker installed, and could easily be moved in the future to run on a Kubernetes cluster.
A second key benefit is to do with density. A virtual machine has a fixed monthly cost whether it is working hard or sitting idle. So if your application spends a lot of its time idle, there can be a strong temptation to host additional applications on the same VM for cost reduction purposes. But now we have to install dependencies for both applications on the same server, with potential for conflicts between them. By containerizing applications it becomes relatively trivial to deploy several containers to the same host VM, without worrying about their dependencies interfering with one another.
My app is a website running on App Service
One very common scenario I encountered at Ignite was people running web applications on Azure App Service. App Service is a very flexible hosting platform that supports the majority of the most popular web programming frameworks including Node.js, PHP, Java and of course ASP.NET and ASP.NET Core. You don't need to containerize your application to run it on App Service.
However, App Service does support containerized web apps using what's known as Web App for Containers. This supports both Linux and Windows (currently in preview) containers. This means you can easily run already-containerized apps (like WordPress for example), as well as use other frameworks that aren't directly supported by App Service, or simply to take greater control over what exact version of a framework you want to use.
Many of the people I spoke to assumed that if they were running say a regular .NET Framework ASP.NET application on App Service, then they ought to containerize it. But my advice was that actually if you're happy on App Service, and the features it offers (which are particularly great for running publicly facing websites and APIs), then there isn't a huge need to containerize. In fact, if you did containerize your .NET Framework ASP.NET app, you'd end up with a Windows container, which is currently significantly more expensive to host on App Service (requiring the Premium Container (Windows) Plan) than running the same application directly as a regular Web App.
So you might not want to containerize in this scenario. One of the key reasons that you would consider doing so, is when you've got multiple web apps that all form part of a larger microservice application, maybe some of which are "front-end" and others "back-end" services. In that scenario, it's likely that before too long you'll start to want some of the more advanced orchestration capabilities that a platform like Kubernetes offers. So you might want to start creating Dockerfiles for all your web apps, even if you currently continue to host them on App Service.
My app is serverless running on Azure Functions
Another question I was asked at Ignite, was whether it would be a good idea to run Azure Functions in a container. Whilst that's completely possible, as Microsoft provide a base image that has the Azure Functions runtime installed, meaning you just need to add in your Function App code.
However, this is another scenario in which containers might not make sense. If you deploy your Function App in a container, you're losing the benefits of the "consumption pricing plan", where you pay only for duration your functions run and you get automatic scale out. By containerizing your function app, you'd need to keep it running yourself, and write your own logic to scale out to multiple instances of the container.
So containerized Function Apps probably only make sense if you want to run outside Azure (although you may also need to avoid integrating with other Azure services like App Insights or Storage Accounts), or maybe if you had an AKS cluster and wanted everything to run inside that for consistency or security reasons.
What might make more sense would be if you could implement a single Azure Function as a container, maybe because it was long-running or had very specific dependencies. That's not currently possible, but I've been experimenting with creating ACI containers from Azure Functions, and hopefully will have something to share on that front soon.
What about my databases?
One question that came up very frequently at Ignite was how to run a SQL Server database in a container. Now it is possible to run databases in containers, assuming that you understand that they should write their data to a volume so that its lifetime is not tied to that particular container instance.
But personally, if I was running a containerized application in Azure and needed a SQL Server database, I would just use Azure SQL Database instead, which offers me a "Platform as a Service database" experience. And there are multiple PaaS database offerings in Azure including Cosmos DB, Azure Database for PostgreSQL, and Azure Database for MySQL. So there is no need to containerize your database in production.
You might however want to use containerized databases for development/test environments, as this can be a way of keeping costs down, as well as allowing you to spin up container images pre-populated with test data. And that's another benefit of containerizing your applications - it is very easy to support multiple configurations for the different environments into which you are deploying it.
What if my app requires Windows?
Another question that came up very frequently, was to do with Windows containers support on Azure Kubernetes Service. If you have legacy Windows apps (e.g. regular .NET Framework apps), they can't run inside Linux containers, so you need a platform that can host Windows containers. Currently, Azure Container Instances, and Azure Service Fabric support Windows containers, with Web App for Containers offering preview support. But unfortunately, Azure Kubernetes Service (AKS) still doesn't offer direct Windows support (unless you count adding Azure Container Instances as a virtual node with the Virtual Kubelet).
This isn't due to a limitation in Kubernetes - in fact, you can already configure a Kubernetes cluster to include Windows nodes, but we're still waiting for AKS to support this. I'm afraid I don't have any insider information about when this might be coming, but I know it is being worked on, and I'm hoping its something we see this year.
The question "should I containerize my cloud application" doesn't have a straightforward yes or no answer, but it depends on what pain points you are experiencing, and what technologies you are currently using. Having said that, there's a good reason why Docker and Kubernetes are exploding in popularity - the problems they solve are ones that are common to many software projects, particularly distributed cloud applications.
If you'd like to learn more about running containers on Azure, I've created an introductory course on Pluralsight (available to everyone for free as part of Microsoft Learn), called Deploying and Managing Containers on Azure.
I can also highly recommend a great book "Docker on Windows" by my friend Elton Stoneman, which provides excellent guidance for containerizing your legacy Windows applications.