Why use Containers?

Containers make it easier to package and run applications

You’ve heard of Docker containers and, maybe you’ve run one or two yourself. But now, you’re wondering what the practical uses for Docker containers are. Beyond docker run redis, what are containers really used for?

Benefits of Containers

The benefits of containers include packaging, portability, isolation and efficiency

Source: Tutorial Works, Vector art by studiogstock on Freepik.com

Containers are used to package and run an application, along with its dependencies, in an isolated, predictable and repeatable way.

Virtual machines can do many of the same things, but they take more time to create, configure, ship, and run. The advantage of a container is that it has all of these benefits, but it’s much faster and more lightweight.

Benefits of containers

Before we look at the main use cases for Docker containers, it’s a good idea to revisit the characteristics of containers and why they’re used in DevOps.

Understanding the benefits of containers will help to understand why they are great for the different use cases that we’ll look at further below.

Containers offer the following benefits:

  • Everything in a single package: A Docker image contains all of an application’s binaries, dependencies and libraries – everything the application needs to run. There’s no need to run an install process.

  • Repeatability: A container image will run the same way, wherever it is run. So once my application is built as a Docker image, I can run my container wherever Docker is installed. I can also run multiple instances of my application very easily, and they will all behave in the same way.

  • Lightweight: Containers are cheap, and fast to create and destroy1. This makes it easier to upgrade and patch software in containers. You don’t modify or upgrade an app inside a container when it’s running: you just kill the old container, and launch a new one with the upgraded application.

    Also, Docker images are comprised of several stacked layers, which saves time when moving images around, as Docker only needs to download the layers which it doesn’t have already.

  • Portability: With Docker, portability comes from the Docker image format. It’s like a zip file (actually it’s a TAR archive) which contains a whole application and all of its dependencies. You can download Docker images from public or private registries, or create your own. A container will run the same on a laptop, in the data center, or in the public cloud.

  • Isolation: A Docker container offers a certain level of isolation. This means that an application runs in its own sealed environment, and cannot affect other applications when it’s running inside a container, unless you choose to allow it.

The benefits of containers vs virtual machines

Virtual machines also have the same benefits that we’ve seen above, but a container offers a thinner level of virtualisation. It doesn’t virtualise an entire operating system, it just virtualises a process. This means that containers have a couple of additional benefits over VMs:

  • Efficiency: Because containers virtualise a single process, they are lightweight and more easily distributed than a virtual machine. They use fewer resources than VMs, they can start up quicker and are easier to scale.

  • Composable: Since containers are lightweight, they can be easily stacked together and swapped around. This is especially useful for microservice architectures, which are made up of many self-contained services, which are independently managed and maintained. Containers are a really good technology to achieve this.

Use cases for containers

So bearing in mind the characteristics of containers, what are some practical use cases for Docker?

With any technology, it’s good to understand the reasons why it exists, and find some practical applications. The concepts are much easier to grasp when you understand what they’re used for.

So let’s look at the main places where you might see containers being used in the real world.

Running third-party applications and utilities

Many popular applications are available as container images. You might find that an application you use regularly is available as a Docker image, which you can pull from one of the public registries.

Here are some examples of applications that you find on Docker Hub, one of the main registries where you can find and download Docker images:

  • PostgreSQL (a database)

  • Python (the programming language)

  • Ubuntu (Linux operating system)

  • Nginx (web server)

The benefits are that the application is packaged in a standard way, includes all of its dependencies, and runs very predictably, wherever it is run. You save all the hassle of having to figure out how to install the application, or set it up manually.

An example - Pandoc

For example, I sometimes use the document processing utility Pandoc. It’s a command-line application which creates PDFs, Word documents, and almost any other type of document you can think of. (It’s very useful!)

Pandoc requires downloading and installing a bunch of stuff onto your laptop, which can be a little complicated.

But, Pandoc is also available as a container image. The image includes Pandoc and all of the dependencies it needs to run. So, whenever I need to use Pandoc to process a document, I can just pull the image, and run Pandoc to do the task I want. I don’t need to worry about whether everything is installed correctly, because the container image includes everything I need.

And at the end, when the utility finishes, the Docker container stops. I can choose to remove the container, and free up any disk space cleanly.

Some other examples of software available as Docker images are: phpMyAdmin, OpenJDK (Java), and Ubuntu (for running Linux in a container).

Deploying software to a cloud platform

Containers are supported by cloud platforms, like AWS, Kubernetes and OpenShift.

This is great for both platform admins and developers, because there is one standard packaging format for building and running apps on the platform.

Administrators don’t need to learn the intricacies of different types of application servers and their libraries, and developers don’t need to understand a whole range of virtualisation technologies.

This is why platforms-as-a-service have generally all adopted containers, and Docker.

The real benefit, as a developer, is that you can package up an application, and everything it needs to run, in a very well-known, portable format, the container image. When your image arrives on the platform, the administrators know how to run it, because it is using the Docker (or OCI) standard.

In the past, this was difficult, because applications used to be deployed in many different ways, via scripts, installers, or even on a VM. But containers have a standard API, which is understood by both developers and system administrators.

This is similar in concept to how applications run on the Apple and Android app stores. Developers package their application in a standard way, and then the cellphone OS knows how to unpack and run those applications, because they use a standard format.

Example: Kubernetes

Kubernetes is an open source container platform. It uses containers as a way of running applications.

This means that if you want to run an application on Kubernetes, you usually need to have it packaged in a container. Kubernetes can pull your container image from a registry, schedule it on a node in the cluster, and start your container.

It can do this because a Docker container conforms to a standard (OCI), so Kubernetes doesn’t need to know a lot of detail about what’s inside the container, or how to start the program inside it.

Running dependencies during development and testing

Many people get started with containers by using Docker while they’re developing software. People use Docker to run one or more of their application’s dependencies.

Often, we waste a lot of time installing and configuring the dependencies that we need for our application. Most applications depend on some other component to run – such as a database, or perhaps an API.

How many times have you needed to access a database, when developing an app? It often requires downloading the dependency and configuring it. The setup time is significant. We can spend a lot of time installing and configuring these complex bits of software – e.g. Oracle Database – just for a few days of actual development time.

But if your application uses a dependency which has been packaged into a Docker image, then you can simply pull the image from a registry, run the container, and you have an instance of your dependency, ready to use immediately.

Example - running MongoDB for an application

A really good example of this is MongoDB. Thousands of applications use MongoDB as a database.

If you run an application which needs MongoDB, you could spend time downloading the MongoDB installer, running the install program, configuring the database, and setting it up.

Or, you could just pull the official MongoDB container image from the Docker Hub registry, and have a database up and running within minutes, with very little configuration.

Then, you point your application to the Mongo instance running in a container.

Compiling software predictably

If you’re developing software, you will probably need to compile or package it. This is especially the case for languages like Java or C. It might seem like a simple task, but the tools you need to compile your program can run into many hundreds of megabytes, and take time to configure properly.

Construction hard hats hanging on a shipping container

Building software with containers

Source: Freepik/Rawpixel

With containers, this process is much easier.

Firstly you create your build environment in a container image. This contains all of your build-time dependencies. Then, when you want to build your software, you can mount your code into the build container, and compile your code. Because each build runs in a fresh instance of the same build container, your builds should run much more predictably.

Example: compiling Java programs

A good example of this use case is compiling Java programs.

To build a Java app, you can use the Maven Docker image, which contains the Maven build tool. You mount your code inside the container, and execute a Maven build. The output from this process is your compiled source code.

The next stage is usually to take this compiled source code (usually a .jar file) and copy it into a new container containing the Java runtime environment, based on the OpenJDK image. Now you have a clean, repeatable process for building a Java application.

See some best practices for using Docker with Java.

Running an application in different environments

This is another example of how Docker is used when developing software. Once you have built a Docker image of your application, it will run in the same way in any environment.

This is made possible because of the standard API provided by container engines like Docker. A container will run predictably on my machine, just in the same way as it does on any other machine.

Starting a container is usually a simple matter of using the docker run command.

This means that containers are a useful way to ship applications between different environments, while maintaining parity between them. In other words, the same application can be run in all environments, by just building one container image, and running it in each environment, with slightly different configuration.

Even if containers aren’t used to run an application in production, they can still be a really valuable way of sharing an application between different environments (e.g. dev, test, UAT) in a predictable way.

Example: Moving an application into test

Containers can be used as one way to move an application from development into test.

Developers can write code, and then ship the application to the test team as a container/Docker image. The test team then runs the container image, and tests the application, without having to follow a complex sequence of steps, configure a server, or even create a virtual machine.

The testing team simply uses docker run to run the image, and the application starts, allowing them to test.

Summary

So, let’s just review. Containers are often used for:

  • Running your application’s dependencies - this is especially useful if you’re a developer and you want to set up a development environment quickly.

  • Creating repeatable, predictable build environments - you can compile your own programs inside a Docker container

  • Moving applications between environments - the Docker image is a very portable format for shipping an application between dev, test and production environments.

  • Packaging and deploying an application on a platform-as-a-service - PaaS platforms like Kubernetes, OpenShift and AWS now enable you to run Docker containers in the cloud.

  • Running utilities or programs so you don’t have to install and configure everything upfront

There are, of course, many more uses for containers. But there is something that ties all of these use cases together: the characteristics of containers, like portability, isolation and repeatability.

I hope you get inspired by seeing these examples of how people are using containers in the real world. It’s a great time to be in software development and I’m excited to see the new use cases that people will come up with for containers.

To learn more about containers, check out the Containers Fundamentals course from Linux Foundation, which will build you a solid foundation in the concepts and techniques.

Happy containerising!