The "Docker" Misconception
When you type docker run nginx, it feels like a single piece of monolithic software called "Docker" grabs an image and runs it. The name "Docker" has become so synonymous with containers that most people assume it is the entire story. It is not.
In the early days of containers (circa 2013–2015), that assumption was mostly correct. Docker was a vertically integrated tool that handled everything: image building, image distribution, networking, storage, and process isolation. But as the container ecosystem matured and more players entered the space, the community deliberately broke Docker apart into smaller, specialized, interoperable tools. Each tool does one thing well and hands off to the next.
Today, what we call "Docker" is primarily a developer-friendly interface — a CLI and a daemon — sitting on top of a layered stack of software components. Understanding this stack is not academic trivia. It is essential for debugging production incidents, reasoning about security boundaries, and understanding how Kubernetes actually works under the hood.
The Russian Dolls of Container Software
Think of running a container like a set of nesting dolls (Matryoshka dolls). Each doll contains a smaller, more specialized one inside it.
- The Outer Shell (User Interface): Tools like the
dockerCLI that accept human-readable commands, handle authentication, and present results in a friendly format. - The Middle Shell (High-Level Runtime): A background daemon that manages the full container lifecycle — pulling images, managing storage volumes, configuring networking, and tracking container state.
- The Inner Shell (Low-Level Runtime): A small, focused binary that talks directly to the Linux kernel to create the isolated sandbox using namespaces and cgroups. It does its job and exits.
Each layer has a clearly defined responsibility. When something goes wrong, knowing which layer is responsible tells you exactly where to look.