The TL;DR
Containers are a way to run code in isolated boxes within an operating system; they help avoid disastrous failures and add some consistency to how you set up applications.
Special software called a hypervisor allows multiple isolated operating systems to run on one computer, and containers do the same for operating systems (đ€Ż)
Containers also provide a consistent environment for deploying software, so developers donât need to configure everything 1000 times
The most popular container engine is Docker: itâs open source and used by >30% of all developers
Containers (and Docker) have spawned an entire new ecosystem of exciting developer tools. You may have heard of Kubernetes, the *checks notes* greek god of container infrastructure. Weâre not going to cover it in this post, but it, too, is Docker related. Needless to say, understanding these little container guys is a really important part of understanding modern software.
Social distancing, but for your bad code
To understand Docker, you need to understand virtual machines.
The first post I ever wrote for Technically was about the cloud, and how companies run their software on big, rented servers instead of building that infrastructure themselves. The biggest provider of that cloud, AWS, is on track to make more than $40B this year (!), and itâs all thanks to one technology: the hypervisor. The hypervisor allows AWS to run code from multiple different people on one server instead of giving everyone their own; itâs a transformational way of building things. But why is this important? And why is it hard to do?
The big hairy truth of software is that your code is going to fail, and itâs going to cause problems. Even those elusive 10x engineers can never quite predict everything (like server environments, but more on that later). And when your code fails, it can blow shit up on your operating system; if youâve ever had to restart your computer because a malfunctioning application froze your whole OS, you can metaphorically raise your hand.

If you want to cram as many peopleâs code onto a server as you can (what AWS does), you need to solve this error problem; you canât let one companyâs code take down everyone elseâs. Hypervisors give you the ability to split one server (one computer) into multiple self contained âboxesâ with individual operating systems and infrastructure (CPUs, RAM, storage). These are called virtual machines (VMs, for short), and this is what youâre getting with AWS EC2.
â Related Concepts â
Virtual machines are the ABCs of cloud, and most companies on a public cloud are probably using them in some form in another. But itâs not just for them: a lot of AWSâs (and GCPâs and Azureâs) more advanced products are built on top of virtual machines under the hood. Virtualization was, and is, a pretty important development.
â Related Concepts â
Now that you (hopefully) understand the concept of isolation and how virtualization (âcreating virtual machinesâ) helps get there, containers are a simple, natural extension of that concept. The problem with hypervisors is that they all run their own operating systems, which take a long time to start from scratch â containers let you run multiple, isolated environments on one operating system. That operating system can be virtual (on a server somewhere), or it can even be on your laptop. So when you run containers on a public cloud server, youâre basically doing isolation2 - a âboxedâ container on top of a âboxedâ virtual machine. đ€Ż

Most importantly: because multiple containers can run on a single operating system, theyâre much faster to spin up.
Developer environments suck
Isolation isnât the only thing that containers bring to the table. A problem that constantly plagues developers is the environment that their code runs in. Code has a lot of dependencies:
Libraries and frameworks
Environment variables
Language versions
Access to data and plugins
Networking between services
All of these (and more!) make up your environment. Every time you install or upgrade a new package, switch to a language version, or allow configure a connection to a database, youâre changing your environment.
đ° Donât sweat the details đ°
If youâre not sure what any of the individual bullet points mean, donât sweat it. Theyâre all code or code-adjacent configurations that impact how your code runs in a given environment.
đ° Donât sweat the details đ°
The typical workflow for developers is to develop locally and then deploy to server. So youâll get code working on your laptop, and then drop it off on a server to run; but that server will almost never have a matching environment to your laptop. Thatâs why thereâs constant debugging to do when you deploy your app.
To make this a bit more concrete, take a look at a few of these kinds of errors that Iâve personally run into:
App built on my laptop in Python uses Python 2, but the server has Python 3 installed
App built on my laptop requires access to my database, but the server is having trouble connecting to it
App built on my laptop needs to write to the
/usr/bin/local
folder, but the server doesnât have permission
These problems are the worst, and theyâre a constant when youâre building and deploying software. But what if you could develop and deploy your code in the same environment, with the same things installed with the same versions? Docker lets you do that. If you build your app in a Docker container on your computer, you can deploy that container â packaged together with all of the dependencies you need â to a server.

Itâs like moving houses, but keeping all of your furniture. And the wallpaper.
Docker 101
Docker is an app like any other: you can download it from the Docker website, and youâll see a little icon with preferences and stuff. When youâre running Docker on a server though, itâs all through the command line. Letâs run through some of the basics:
Docker images
The basic starting point for a Docker container is an image. An image is like a blueprint for what you want your containers to look like: once youâve built an image, you can create infinite containers from it that look exactly the same. A Docker image is just a static file, which makes it very sharable: Docker even has a product called Docker Hub where you can host and share your container images.
The Dockerfile
The Dockerfile (aptly named) is how you actually build a Docker image. Itâs just a text file with a series of commands that tell the operating system what to do when youâre building a container: install this version of this package, run this script, open this port, etc. Itâs common practice to use someone elseâs publicly available Docker image as a base and build from there (this is usually called âpullingâ an image).
Orchestrating containers for scale - đ€© Kubernetes đ€©
The terminology around Docker and containers is a lot like virtual machines: you spin them up and spin them down. Thatâs because another major benefit of a containerized architecture is easier scale. If your application is growing and needs more resources, you can spin up new Docker containers easily. Docker takes care of networking them together and other low level utilities like that; but thatâs just the start. This is where Kubernetes comes in.
Big apps (and today, for some reason, even small ones) can be made up of a bunch of Docker containers: one for the app, one for the database, one for adjacent services, and so on. Orchestrating this complex workflow and making sure the right containers are running at the right time (and that they can talk to each other) is a hard job, and that (in a nutshell) is what Kubernetes does. Docker also has Swarm, which takes on a similar, more tightly scoped version of this. More on that in a future post.
Learning more
This is just a basic intro to containers. If youâre looking to learn more, here are a few areas to dive deeper into:
Managed services
As containers have become more ingrained in the developer workflow, managed services have begun popping up. They automate parts of the infrastructure youâd need to run containers. The best example is AWSâs ECS (elastic container service), which takes care of deploying containers and some orchestration tasks too. AWS also offers Fargate, a serverless (think: no infrastructure management) option for deploying containers.
Kubernetes and orchestration
Kubernetes is really popular, and not just because of all of my jokes on Twitter about it; itâs becoming one of the (almost) default ways that modern apps are getting deployed, for better or for worse. Kubernetes, or K8s for short, is a very complicated piece of software to work with, and there are a lot of âshiny new thingâ decisions being made. Your basic web app didnât need Kubernetes 10 years ago and it probably doesnât need it now.
Networking and volumes
A lot of the âenvironmentâ problem comes down to connecting things together. If your data is in one container and your main app service in another, they need to correct configuration to talk to each other without letting just anyone in. Docker has an entire networking layer that takes care of this.
A related problem â since containers are ephemeral, systems need a way to keep important data around (if you destroyed data when you destroyed containers, weâd never remember anything). Dockerâs Volumes functionality helps persist that data so you can continue working with it.
Serverless and lightweight virtualization
Containers are all the rage, but as with literally everything in software, thereâs something new-er and cool-er on the horizon. One of those things is serverless (post coming soon!) â itâs a way of deploying functions instead of an entire app, and avoiding having to work with any infrastructure (like VMs) at all. AWS is also working on a new lightweight virtualization tool called Firecracker that has the potential to re-paint this entire picture.
Terms and concepts covered
Virtual machine, virtualization
Hypervisor
Isolation
Environment
Docker
Image
Dockerfile
Orchestration
Kubernetes
Networking
Volumes
(phew)
26 | 3 |
Really technically. I recently learned how to use Docker. However, the image is like the template? correct me if I'm wrong.