Lesson 1 of 15 · Fundamentals
Why containers?
Objective
Understand the problem that Docker solves and what a container really is. Master the basic vocabulary: image, container, registry, Docker Engine and OCI. This lesson requires no installation.
Key points
- A container is an isolated Linux process. It has its own view of files, of the network and of other processes, but it uses the kernel of the host machine.
- An image is a frozen, read-only template (the program, its libraries, its configuration). You can start as many containers as you want from the same image.
- A registry stores and distributes images (Docker Hub, GitHub Container Registry, a private registry).
- Docker Engine is the engine: a daemon (
dockerd) that builds images and runs containers, driven by thedockercommand. - The OCI standard (Open Container Initiative) describes the image format and how to run images. An image built with Docker also runs with Podman, containerd or Kubernetes.
The problem: "it works on my machine"
Imagine an online shop in Casablanca. The developer wrote the site with Node.js 22 on an Ubuntu laptop. The production server runs Debian with Node.js 18. On launch day, a library refuses to start: the Node version does not match, a system package is missing, an environment variable was forgotten.
This problem has three classic causes:
- Dependencies differ from one machine to another (language versions, system libraries).
- Configuration is not written down: it lives in someone's head.
- Several applications on the same server get in each other's way (one wants PHP 8.1, the other PHP 8.3).
A container fixes these three points. The application travels with everything it needs, the recipe is written in a file (the Dockerfile), and each application has its own space, isolated from the others.
Virtual machine versus container
A virtual machine (VM) simulates a complete computer: a virtual processor, a virtual disk and, above all, its own operating system with its own kernel. A hypervisor (VMware, KVM, Hyper-V, VirtualBox) shares the hardware between the VMs.
A container simulates nothing. It is a normal process of the host system, which the Linux kernel confines with two mechanisms:
- namespaces: the process has its own process list (
pid), its own network (net), its own mount points (mnt), its own hostname (uts), its own users (user), and so on; - control groups (cgroups): the kernel limits the memory, CPU and I/O that this process can consume.
| Criterion | Virtual machine | Container |
|---|---|---|
| What is isolated | an entire machine | a process (and its children) |
| Kernel | one kernel per VM | the host kernel, shared |
| Typical size | several GB | a few MB to a few hundred MB |
| Startup | tens of seconds | a fraction of a second |
| Possible systems | any (Windows inside Linux…) | Linux programs on a Linux kernel |
| Density | a few VMs per server | tens or hundreds of containers |
| Isolation | very strong (virtual hardware) | good, but depends on the shared kernel |
The two are not opposites. In real life, you very often rent a VM (a VPS from a hosting provider) and run containers on it.
Windows and macOS have no Linux kernel. Docker Desktop therefore starts a small Linux VM in the background, and your containers run inside it.
You can see the namespaces of any Linux process, even without Docker:
ls /proc/self/ns # namespaces of the current shell
# cgroup ipc mnt net pid pid_for_children time time_for_children user uts
cat /proc/self/cgroup # the control group it belongs to
uname -r # the kernel: the SAME for the host and all its containers
Image and container
The best mental model is the class and the object in programming, or the mould and the cake:
- the image is the mould: immutable, versioned, shareable;
- the container is a cake taken out of the mould: a living instance that starts, works, stops and can be deleted.
An image is made of stacked layers. Each layer adds, changes or deletes files compared with the previous one. When a container starts, Docker places a thin writable layer on top, specific to that container. This has a major consequence:
Everything a container writes to its layer disappears when you delete it. Data you want to keep (a database, files uploaded by customers) goes into a volume. You will see this in detail in level 2.
Two principles guide how you use images:
- You do not modify an image. To change something, you build a new image (a new version), delete the old container and start a new one.
- One container, one role. The website in one container, the PostgreSQL database in another, the Redis cache in a third. You then assemble them with Docker Compose.
Registries and image names
A registry is a server that stores images, a bit like an apt or dnf package repository. Docker Hub is the default public registry. There are many others: GitHub Container Registry (ghcr.io), cloud registries (Amazon ECR, Azure ACR, Google), GitLab, Harbor… and you can host your own.
The full name of an image has three parts:
ghcr.io / startup-rabat/api : 2.3.1
└──┬──┘ └──────┬────────┘ └─┬─┘
registry repository tag
When a part is missing, Docker fills it in:
| You write | Docker understands |
|---|---|
nginx |
docker.io/library/nginx:latest |
nginx:1.27-alpine |
docker.io/library/nginx:1.27-alpine |
ecole/inscriptions:2.0 |
docker.io/ecole/inscriptions:2.0 |
ghcr.io/startup-rabat/api:2.3.1 |
(name already complete) |
- No registry:
docker.io(Docker Hub). - No namespace:
library/, the folder of official images (nginx, postgres, redis, node, debian…). - No tag:
latest. This word does not mean "the most recent". It is just the default tag. In production, always write a specific tag.
Docker Engine: who does what?
When you type docker run nginx, several programs work together:
you ──> docker (client, the command)
│ REST API on /var/run/docker.sock
▼
dockerd (the Docker Engine daemon)
│ images, networks, volumes, builds (BuildKit)
▼
containerd ──> runc ──> the isolated process (your container)
dockeris the client. It runs nothing itself: it sends orders to the daemon's API. It can even talk to a remote daemon.dockerdis the daemon. It manages images, networks, volumes and builds.containerdmanages the container lifecycle, andruncactually creates the isolated process (namespaces, cgroups).
The daemon runs as root. Anyone who can talk to its socket can therefore do anything on the machine. You will see in level 4 what this means for security.
OCI: an open standard
In 2015, Docker and other players created the Open Container Initiative. It publishes open specifications:
- image-spec: the format of an image (layers, manifest, configuration);
- runtime-spec: how to run a container from an unpacked image;
- distribution-spec: how a registry receives and distributes images.
Thanks to OCI, you are not locked into one tool. An image built by Docker on a developer's laptop can be started by Podman on a Red Hat server, by containerd in Kubernetes, or stored in any compatible registry.
Why Docker became essential
| Need | What Docker brings |
|---|---|
| Install an application in 5 minutes | docker run an official image, nothing to compile |
| Reproduce a production bug | run exactly the same image locally |
| Deploy often and safely | new image = new version; rollback = restart the old one |
| Run several versions side by side | PHP 8.1 and PHP 8.3 in two containers, on the same server |
| Continuous integration (CI) | each test starts in a clean, identical environment |
| Prepare for Kubernetes | Kubernetes orchestrates… containers built as shown here |
A concrete example: the registration application of a school in Fès consists of a website, an API and a PostgreSQL database. With Docker, a new developer clones the project, types a single command (docker compose up), and gets the same stack as production within a minute.
A bit of history
Containers were not born with Docker. They are the result of twenty years of additions to the Unix world and the Linux kernel:
| Year | Milestone |
|---|---|
| 1979 | chroot on Unix: a process sees another folder as its root / |
| 2000 | FreeBSD jails: isolation of processes and network |
| 2004 | Solaris zones |
| 2002-2013 | namespaces arrive one by one in the Linux kernel; cgroups (proposed by Google) are added in 2008 |
| 2008 | LXC: the first complete Linux containers, but hard to use |
| 2013 | Docker: a simple command, layered images, a public registry |
| 2015 | creation of the OCI; Kubernetes 1.0 |
| 2017-2019 | Docker hands containerd over to the CNCF foundation; Podman (Red Hat) arrives |
| today | Docker Engine, Podman, containerd and Kubernetes share the same image format |
Docker's real revolution was not technical. It was to package these mechanisms into a simple tool, with a portable image format and a registry where everyone shares their images.
Docker, Podman, containerd: which one to use?
You will come across several tools. They all speak the same image language:
| Tool | What it is | Where you find it |
|---|---|---|
| Docker Engine | daemon + docker client, Compose, BuildKit |
Debian/Ubuntu servers, VPS, developer workstations |
| Docker Desktop | graphical application with a built-in Linux VM | Windows and macOS workstations |
| Podman | same commands as Docker, no daemon, native rootless | RHEL, Rocky, AlmaLinux, Fedora |
| containerd | low-level engine, without a user-friendly interface | under Docker, and in most Kubernetes clusters |
This course uses Docker Engine and Docker Compose, the most widespread at hosting providers and in job offers. Everything you learn about images and Dockerfiles also applies to Podman.
Vocabulary at a glance
| Word | Short definition |
|---|---|
| Image | read-only template, made of layers, identified by a name and a tag |
| Container | running instance of an image, with a disposable writable layer |
| Layer | a set of file changes, shared between images |
| Registry | server that stores and distributes images |
| Repository | all the versions of the same image in a registry |
| Tag | name of a version: 1.27, 1.27-alpine, latest |
| Dockerfile | text recipe that describes how to build an image |
| Volume | storage space managed by Docker, which outlives containers |
| Compose | tool that describes and starts several containers with a YAML file |
Common pitfalls
- Thinking a container is a small VM: it has no kernel of its own. A kernel module or a global
sysctlsetting is configured on the host. - Storing important data inside the container: it disappears when the container is deleted. Use a volume.
- Using
latestin production: you no longer know which version is running, and a simple restart can change the version. - Pulling any image from Docker Hub: prefer official images or images from verified publishers, just as you would choose a trusted package repository.
Lab
Docker is not installed in the lab: it is not needed here. You will:
- list the namespaces of a process, the basic building block of a container;
- record the kernel version, the kernel that all containers on the machine would share;
- write the full name of an official image;
- break down the name of an image hosted on GitHub Container Registry.
Quiz
- What is the fundamental difference between a virtual machine and a container?
- What are the two Linux kernel mechanisms that isolate and limit a container?
- What happens to a file that a container wrote to its own layer when you delete the container?
- What full name does Docker use for
redis? - What is the OCI standard useful for, for a company?
Answers
- A VM carries its own system and its own kernel on virtual hardware. A container is an isolated process of the host that shares the host kernel.
- Namespaces for isolation, and control groups (cgroups) to limit resources.
- It is lost. Data to keep must go into a volume or a mounted folder.
docker.io/library/redis:latest.- It guarantees that an image is not tied to one tool: built with Docker, it can run with Podman, containerd or Kubernetes, and be stored in any compatible registry.
Reference sources: official Docker documentation (docs.docker.com, Apache 2.0 license). Original MasterLinux text.