Containers: what they are and why they won
What a container really is, why "it works on my machine" stopped being an excuse, how containers differ from VMs and bare metal, and where Docker and OCI fit.
By the end of this lesson you'll be able to
0 of 4 complete"It works on my machine"
The app runs perfectly on your laptop. On the server it crashes, because the server has Python 3.10 and you have 3.12, or a library is a different version, or a config file is in a different place. Every team has lost days to this.
Containers fix it by shipping the app together with everything it needs: the runtime, the libraries, the system tools and the config defaults, all frozen into one image. If the image runs on your laptop, the same image runs the same way on the server, in CI and on your colleague's machine.
That one property changes a lot:
- Developers stop writing "install these 14 things" in the README.
docker runis the setup. - Operations gets one way to run every app, whatever language it's written in.
- Pipelines build one artifact and deploy it everywhere, as the CI/CD course explains.
- Density. Many isolated apps can share one server without fighting over library versions.
What a container actually is
A container is a normal Linux process that the kernel isolates. It's not a small VM and there's no second operating system inside it. Two kernel features do the work:
- Namespaces change what the process can see: its own process list, its own network interfaces, its own hostname and its own filesystem.
- cgroups limit what it can use: how much CPU, memory and I/O.
The filesystem comes from the image: a read-only stack of layers holding the app and its dependencies. When a container starts, it gets a thin writable layer on top, which disappears when the container is removed.
You can see the isolation yourself:
$ docker run --rm alpine ps # the process list inside a new container PID USER TIME COMMAND 1 root 0:00 ps $ docker run --rm alpine cat /etc/os-release | head -n 2 NAME="Alpine Linux" ID=alpine
docker run --rm alpine psdockerbuild and run containersrunstart a new container--rmdelete the container when it exitsalpinea value the command works onpsa value the command works on
docker run --rm alpine cat /etc/os-release | head -n 2dockerbuild and run containersrunstart a new container--rmdelete the container when it exitsalpinea value the command works oncata value the command works on/etc/os-releasea path|pipe: send output to the next commandheadshow the first lines-nhow many lines2a value the command works on
Inside the container, ps is PID 1 and sees nothing else on your machine, and the filesystem
is Alpine Linux, whatever your host runs. --rm deletes the container when it exits, so you
don't collect stopped containers while you experiment.
Bare metal, VMs and containers
| Bare metal | Virtual machine | Container | |
|---|---|---|---|
| What you get | A whole physical server | A full OS with its own kernel | Isolated processes on the host kernel |
| Starts in | Minutes (boot the hardware) | Tens of seconds to minutes | Usually under a second |
| Size | The whole machine | Gigabytes | Megabytes to a few hundred MB |
| Isolation | Complete | Strong: separate kernels | Good, but one shared kernel |
| Use it for | Databases, raw performance | Different OSes, strong tenant isolation | Apps and services, CI jobs, microservices |
They aren't rivals. In the cloud you'll nearly always run containers inside VMs: the VM gives you strong isolation from other customers, and containers let you pack many apps onto it.
Docker and OCI
Docker made containers easy in 2013 with three ideas: a simple file to describe an image
(the Dockerfile), a command line that builds and runs it (docker build, docker run), and a
registry to share images (Docker Hub). The kernel features existed before; Docker made them
usable.
Under the hood, Docker is several pieces:
| Piece | Does |
|---|---|
docker CLI | What you type. Sends requests to the engine |
Docker Engine (dockerd) | Builds images, manages containers, networks and volumes |
| containerd | Runs and supervises containers. Kubernetes uses it directly |
| runc | Talks to the kernel to create the namespaces and cgroups |
The Open Container Initiative (OCI) turned the image format and the runtime into open standards. That's why an image you build with Docker also runs on Podman, on containerd, on Kubernetes and on every cloud container service. Learn Docker and you've learned how containers work everywhere.
$ docker run hello-world Hello from Docker! This message shows that your installation appears to be working correctly. ... $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest ... ... ~8MB # yours will differ a little hello-world latest ... ... a few kB
docker run hello-worlddockerbuild and run containersrunstart a new containerhello-worlda value the command works on
docker imagesdockerbuild and run containersimageslist images
Prove a container shares the host kernel
A teammate insists every container runs its own operating system, like a VM. Settle it on a Linux machine: record the host's kernel version and the kernel version seen from inside an Alpine container, side by side in one file.
~/kernel-check.txtReveal one safe solution
$ echo "host: $(uname -r)" > ~/kernel-check.txt $ echo "container: $(docker run --rm alpine uname -r)" >> ~/kernel-check.txt $ cat ~/kernel-check.txt host: 6.8.0-48-generic container: 6.8.0-48-generic
echo "host: $(uname -r)" > ~/kernel-check.txtechoprint text"host: $(uname -r)"text, kept together by the quotes>write output to a file, replacing it~/kernel-check.txta path
echo "container: $(docker run --rm alpine uname -r)" >> ~/kernel-check.txtechoprint text"container: $(docker run --rm alpine uname -r)"text, kept together by the quotes>>append output to a file~/kernel-check.txta path
cat ~/kernel-check.txtcatprint a file~/kernel-check.txta path
The numbers match because there's only one kernel. The container's files say Alpine, but the kernel underneath is the host's. On Docker Desktop you'll see the kernel of its Linux VM instead, which proves the same point.
Try it yourself
0 of 5 steps doneRun each task in your own account or terminal, then tick it off.
Quick check
What does every container on a Linux host share with the host?
Official reading for this lesson
Or get every quiz answer right and it completes itself.