Containers 101: The why, what and how of containers

A software container is a sandbox for application – and a little bit more.

Fancy setting sail on the deep blue container sea? 🐳 You’ve come to the right place! In this article, we’re going to simplify containers – perhaps the most misunderstood concept in tech right now.

A container is a sandbox for an application.

Containers are a modern way to run apps on your laptop, package your own apps, and even run apps in data centers.

In short, they’re a super flexible way to share and run applications.

But how exactly does a container work? And how do you run one?

In this article, we’ll take a look at what a container actually is, the difference between a container and an image, and we’ll see an example of containers in action.

Tip! Once you’ve understood containers first, you’ll be more confident to tackle complex topics like Kubernetes.

What is a container?

First, let’s look at what a container actually is:

A container is a virtual environment for running a program, which restricts the program’s access to things like files and resources on the computer.

Creating a container is a bit like creating a sandbox for an application. When an app is running inside a container, it gets a restricted view, which gives it limited access to other files and processes.

What is a sandbox?

A sandbox is a technical term that means separating a program from others on a server, or restricting the things that a program can do.

When you sandbox a program, you usually do it to protect other programs or data on the system, in case something goes wrong.

The term comes from a children’s sandbox – which is usually a safe place for a child to play! (Or you might know it as a ‘sandpit’ in other countries.)

A container puts a program in jail

A container is a bit like a jail cell for a program – isolated and quarantined from the rest of the system.

Containerised applications running on a Linux server

Containers are like cages for your applications

Inside its jail cell, a containerised process can only do a limited amount of stuff:

  • It can only see a certain set of files

  • It can’t see other processes running on the same host

  • It can be allocated a restricted amount of memory or CPU

  • Its network ports aren’t exposed outside the container

This means that you can run many containers on the same host, and there’s less risk of them interfering with each other (…unless they figure out how to escape the jail!)

Yes, the containers in the diagram above are glass boxes – for artistic purposes 😉… So pretend it’s one-way glass: We can see all the processes, but they can’t see each other.

How does the isolation work?

The container runtime (e.g. Docker) uses some advanced Linux features – like cgroups (which controls access to resources), namespaces (which controls the visibility of resources) and chroot (which controls access to the filesystem) – to restrict what a process can see and do.

Most of this fiddly configuration work is done for you by the container runtime when you create and run a container.

Container images

We’ve seen a bit about containers. Now let’s look at images.

Images were created and popularised by Docker, so they’re often called Docker images.

But what exactly is an image, and what is it used for?

What is an image? 💾

A container image is just a package of bits and bytes, which contains all the files and settings needed to create a container.

A container is usually created from an image. You can think of an image like a template or blueprint for creating containers.

You can create hundreds (or millions) of containers from the same image.

Images can be stored on your local machine, and you can share them with others.

An image contains everything

Most applications need libraries and system utilities to run. Or, perhaps they depend on another program.

A container image contains everything you need to run an app.

But when you create a container image, you package all of your app’s dependencies into the image.

This means that when you download someone else’s container image (called pulling an image), you shouldn’t need to fetch or install anything else.

The container image should contain everything that you need to run the application.

Images have layers

Container images are mightily efficient, because they’re made up of layers.

The layers in a container image work in a kind of hierarchy:

Each image layer builds on top of the previous layer.

When the container starts, all the image layers are combined together. This initialises the container’s file system.

You can create your own container image by simply adding a new layer on top of an existing image.

This makes container images efficient, because many different images can share the same layer. This can translate into big savings when shifting container images across a network.

Images have tags

Images can have different versions, called tags.

This lets you create multiple versions of the same image.

Perhaps you’re developing an app, and you want to publish a different container image for each minor release of your app – e.g. v1.0, v1.1, v1.2, etc.

Or you’re working on a new feature of an app, and you want to share a test version, so you want to publish an image labelled ‘test’. You can do that with tags.

Building an image 🔨

To build a container image, you can use few different ways:

  • Create an image manually: You can start a container, make some changes to it, and then commit your changes into a new image. This is a bit fiddly - but absolutely fine if you’re just creating an image for yourself.

  • Write a Dockerfile: You write a set of instructions that tells Docker how to build an image, with the docker build command.

  • Command-line tools: You can use a dedicated image-building tool, like Bazel by Google, Buildah or Pack.

There are a few different container image formats, but the most common one is the OCI image format. Fortunately all of these tools support this format!

Containers vs VMs

So far, these characteristics seem very similar to those of virtual machines. Isolation… restricted access… So isn’t a container the same as a virtual machine?

Actually, not quite:

A container lets you isolate a process (and its files) on an operating system.

Containers are “process-level” isolation. Typically, when a container starts, the process inside the container also starts. And when the process ends, the container also stops.

But, by contrast, a ‘traditional’ virtual machine runs an entire operating system, including its kernel.

This key difference means that the isolation between containers isn’t as “deep” as it is with VMs. But, it also means that containers are a little more lightweight than VMs, and carry less overhead.1

Can containers completely replace VMs?

Containers are a good way to package and run apps, but they probably won’t replace VMs entirely. Not just yet, anyway.

For example: let’s say that you want to run a different operating system on your computer – e.g. you want to run Windows on a Linux server, or Linux on Windows. You’ll still need to use a virtual machine for that2.

And there are plenty of other use cases where containers just wouldn’t be a good enough replacement for VMs.

But, you can run containers on top of VMs. This is essentially what happens when you run a container on a cloud service like AWS: you run a container, which runs inside a VM, which is running on bare metal. Whoa. 😵‍💫

Example: Running a container

You can run a container anywhere – as long as you’ve got a container runtime installed.

There are a few different container runtimes, but the most well-known is Docker.

So let’s see an example of starting a container with Docker.

Starting an Apache container with Docker

Let’s try running a container with Docker.

We’ll try to run the application Apache HTTP Server.

Apache is one of the most popular web servers on the planet! And, fortunately for us, it’s available as a container image.

Let’s try it:

  1. First install Docker for your platform.

    On Windows and Mac, you can install Docker Desktop, or on a Linux environment you want Docker Server.

  2. Once Docker is installed, open up a Terminal, and type:

    docker pull httpd
    

    This downloads the Apache image from the main public registry, Docker Hub.

  3. Now to start a new container, type:

    docker run httpd
    
  4. Apache is now running!

    It’s running in the foreground, so you can press Ctrl+C to exit.

Pretty simple, right? No Apache installation or configuration needed.

Everything happened inside the container. All we needed to do was pull the Apache image and run it.

Your questions answered

Because you’ve probably got questions (or, like us, you like to learn by reading other people’s queries), here are some of the most common questions that people have about containers:

What's the difference between a container and an image?

In container terminology, there is a distinction between a container and an image.

A container is an application or process that runs inside a jail, with restricted access to other stuff on the host system. When you type docker ps, you’re seeing a list of running containers.

Meanwhile, the image is like a source file or template for creating containers. You can start multiple containers from a single image. In Docker, you can see a list of images you’ve downloaded by typing docker images.

Can I run a Linux container on Windows?

Most images in Docker Hub are Linux container images. So how do you run them on Windows?!

Strictly speaking, you can’t run a Linux container directly on Windows2, because a Linux container needs a Linux kernel.

However, you can run a Linux container inside a Linux virtual machine (VM) running on Windows. On your Windows PC, you create a Linux VM, install a container engine like Docker, and use that to run your Linux containers.

It sounds a bit confusing, but this is actually how Docker Desktop works. Behind the scenes, it fires up a Linux VM to run your Linux containers (see Docker’s blog all about it).

Got a question of your own? Let us know in the comments box at the bottom, and we’ll answer it!

Wrapping up

In this article we’ve looked at the very basics of containers. We’ve seen that:

  • A container is a way to isolate a program on an operating system

  • A containerised process has a limited view, and can only access certain files and resources

  • Unlike VMs, containers share the same underlying operating system kernel

Did this clear things up for you? Let us know in the comments below!

Further reading

There are some excellent technical blogs elsewhere on the web if you want to dive into this topic a little more:

Now you’ve grasped the basics, you should take a look at how containers communicate with each other – check out our article on container networking. ⚡