Building modern environments based on Cloud native principles requires a rethink of many factors. One of them is the way we build and deploy an application to the environment. You should have heard about containers but we will go a step further and introduce the immutable images running in a container.
What is an immutable image running in a container?
Let's first try to understand what a container is. A container - a scale unit of distributed system, that is an isolated ecosystem to run a specific process, a binary or an application. It is clear that a specific process requires a running environment such as a language interpreter, system dependencies which are needed to run that interpreter and the programme - a source code - that it is going to be launched on.
Technically speaking, if you run an application in a container you need to have acbase image and your a code containing the source code from the last commit to the application repository. Having those two parts connected together, you can build an image that includes the only things which are required to run an app. The final image will contain the running environment from the base image, the source code of your application and all the dependencies. That final image is called the immutable image of your application.
In other words, once the image with your code is created, it cannot be changed at all via any user modification or interactions. There is no incremental change to the already created image. If you are going to change anything inside the container e.g. add any new features, update the config files, you have to commit your changes to the repository and build a new image of your application.
The image can be called artefact which can be stored in an image repository and has its own version, tags and other naming convention. Typically the image is tagged with last GIT Commit id.
git rev-list -1 HEAD --abbrev-commit as a version.
Once the image is built, it can be stored in an image registry like ECR, GCR, Docker Hub or Harbor. You can keep even previous versions of your immutable in your repository. That image can be deployed and released in your environment.
The older version of the image still exists allowing an easy rollback to the previous version of the application if an error occurs. That workflow can be customized based on your needs.
The entire process from the commit, through build process and finally pushing to the environment has to be automated. You can add other tasks to that process such as security scanning of your image. That automate process can to be managed by CI/CD platforms.
Currently, immutable containers are the core of all the modern environments. Once you learn how to build your own container images with your source code, you will enter another level of managing the entire application lifecycle. It is the first step to leveraging cloud-native environments.
Working with immutable containers introduces you to Kubernetes, which is a container orchestration solution. It is an absolutely separate topic requiring lots of experience and knowledge but definitely the core of it is an immutable container.
What are the benefits of having immutable images?
The immutable image contains everything that is required to run an application in a container. You can share the same image across all of your environments including development, staging and production. You can change the behaviour of you image by injecting the variables specific to the environment .e.g
once the container is deployed. The values of those environments are different for staging and production but the immutable image is the same.
The image can easily be scaled up depending on the overall load of your application. Please note that your image is self-sufficient so you can replicate more instances of your image across the entire environment. That process can also be automated based on the given metrics. It is already addressed by Kubernetes Horizontal Pod Autoscaller. The cluster can take decisions to run more instances of the self-sufficient image because the number of incoming requests is growing. If you don’t need those instances, you can automatically turn them off and reduce the overall costs of your infrastructure. You can compare that to turning off the light in your apartment if you don’t need it in a room
If you deploy your image and you experience any unexpected behaviour, you can easily rollback to the previous version. The previous version can be easily stored in the image registry. The rollback process is much simpler if you have an immutable image with the previous version.
Different techniques of deployment
You can deploy a few versions of your immutable image on your environment but you can route the incoming traffic to one version only. The new version of the app is deployed but no production traffic is routed yet. Once you decide to switch the traffic to the new version, you release the app. That’s the major difference between release and deployment. The release process can be done within a specific period of time and it is called canary deployment. There are far more deployment techniques but that one is very powerful and provides lots of business advantages. I will write more about that in the next article.
Summarising, working with immutable images gives us a few important advantages such as:
- immutable container does not interact with the entire system, it is an isolated ecosystem, it does not directly interact with files and libraries installed on the host system.
- an artefact / an image contains and runs the application in the exact version.
- An image has the exact version of running environment such as libraries and all dependencies.
- Many versions can be kept in the repository and switching between them can be relatively easy, which means that rollback to a previous version should be possible.
- Using image running in a container that can be scaled up horizontally encourages us to develop a distributed system and use cluster orchestration to manage deployed workflows.
and find out more detailed information!