DevOpsDocker

What Is Docker? Containers, Images & the Problem They Solve

Learn what Docker is and why it exists. Understand containers vs virtual machines, Docker images, the Docker daemon, and how Docker solves the 'works on my machine' problem.

TT
Daniel Brooks
6 min read
What Is Docker? Containers, Images & the Problem They Solve

"It works on my machine." Every developer has said it. The code runs fine locally but fails in staging, or breaks on a colleague's laptop because they have a different version of Node, Python, or a system library. Docker was built to eliminate this problem.

Docker is a platform for packaging, distributing, and running applications in containers — isolated, portable units that include everything the application needs to run. This lesson explains what Docker is, why containers exist, and how Docker differs from virtual machines.


The Problem Docker Solves

Modern applications depend on a precise combination of runtime versions, libraries, environment variables, and configuration. Getting that combination exactly right across development, staging, and production environments — and across team members' laptops — is surprisingly hard.

The traditional solution was documentation ("install Python 3.11, then pip install these packages, then set these environment variables..."). This is fragile, error-prone, and doesn't scale.

Docker's solution is to package the application together with its entire environment into a single, portable unit. That unit — a container — runs identically everywhere Docker is installed.


What Is a Container?

A container is an isolated process on the host machine. It has its own filesystem, its own network interface, its own process namespace — but it shares the host operating system's kernel.

Think of it like a self-contained apartment within a building. Each apartment (container) has its own interior (filesystem, dependencies, environment), but all apartments share the building's structural infrastructure (the OS kernel). This is fundamentally different from a virtual machine, which is more like having a separate building entirely.

What a Container Includes

  • The application code
  • The runtime (Node.js, Python, Java JDK, etc.) at a specific version
  • All dependencies (npm packages, pip libraries, system packages)
  • Environment variables and configuration
  • A minimal filesystem layer

What a Container Does NOT Include

  • A full operating system kernel
  • A hypervisor
  • Virtualised hardware

This is why containers start in milliseconds, use tens of megabytes instead of gigabytes, and can run dozens on a modest laptop.


Containers vs Virtual Machines

Both containers and VMs provide isolation, but they achieve it differently:

AspectContainerVirtual Machine
Isolation levelProcess / filesystemFull hardware virtualisation
Startup timeMillisecondsMinutes
SizeMBsGBs
OSShares host kernelFull guest OS
Performance overheadNear-zeroSignificant
DensityHundreds per hostTens per host
Security isolationGood (namespaces + cgroups)Stronger (hardware boundary)
Use caseApplication packagingFull OS isolation, legacy apps

Containers and VMs are not mutually exclusive — in cloud environments, containers usually run inside VMs. Docker runs inside an EC2 instance or a GCE VM, combining both layers.


The Docker Architecture

Docker uses a client-server architecture:

text
Docker CLI (client)
       |
       | REST API
       ↓
Docker Daemon (dockerd) — runs on the host
       |
       ├── Images (stored locally)
       ├── Containers (running processes)
       ├── Networks
       └── Volumes

Docker Daemon (dockerd)

The Docker daemon is a background service that manages all Docker objects — images, containers, networks, and volumes. It listens for Docker API requests.

Docker CLI

The command-line tool you type docker commands into. It communicates with the daemon via the Docker API. When you run docker run nginx, the CLI sends that instruction to the daemon, which does the actual work.

Docker Registry

A storage and distribution system for Docker images. Docker Hub is the default public registry — it hosts official images for thousands of popular software packages. You can also run private registries.


What Is a Docker Image?

A Docker image is a read-only template used to create containers. It's a layered filesystem snapshot: each layer represents a change to the filesystem (install a package, copy a file, set an environment variable).

Think of an image as a recipe and a container as the meal cooked from it. You can cook many meals from the same recipe; you can run many containers from the same image.

text
nginx:1.25 image layers:
  Layer 4: COPY app files
  Layer 3: RUN npm install
  Layer 2: Install Node.js 20
  Layer 1: Debian slim base

Images are immutable. You can't change a running image — you build a new one. This immutability is what guarantees containers run identically regardless of where or when they're started.


The Docker Workflow

The typical Docker workflow has four steps:

  1. Write a Dockerfile — instructions for building your image
  2. Build the imagedocker build processes the Dockerfile and creates the image
  3. Push to a registrydocker push uploads the image to Docker Hub or a private registry
  4. Run containersdocker run pulls the image and starts a container from it
bash
# Build an image tagged "myapp:1.0"
docker build -t myapp:1.0 .

# Push to Docker Hub
docker push myusername/myapp:1.0

# Run a container from it
docker run -p 3000:3000 myusername/myapp:1.0

In production, step 4 is typically handled by Kubernetes rather than running docker run manually.


Key Docker Concepts at a Glance

ConceptDescription
ImageRead-only blueprint for creating containers
ContainerRunning instance of an image
DockerfileText file with build instructions
RegistryStorage for images (Docker Hub, ECR, GCR)
LayerA filesystem change cached as part of an image
VolumePersistent storage mounted into a container
NetworkVirtual network connecting containers
DaemonBackground service managing Docker objects

Why Docker Changed Everything

Before Docker (2013), deploying an application meant configuring servers manually, managing dependency conflicts, and hoping that "works on my machine" translated to "works in production." Configuration management tools (Chef, Puppet, Ansible) helped, but they operated at the machine level rather than the application level.

Docker shifted the packaging boundary from "the machine" to "the application." Once you containerise an app, it doesn't matter whether it's running on Ubuntu 20 or 22, on your MacBook or an EC2 instance — the container behaves identically.

This shift enabled microservices (each service runs in its own container with its own runtime and dependencies), CI/CD pipelines (build once, deploy the same image everywhere), infrastructure as code (Dockerfiles version-control your environment alongside your application), and ultimately Kubernetes (container orchestration at scale becomes possible when the unit of deployment is a portable image).


Next: Lesson 2 — How to Install Docker


Part of the Docker & Kubernetes Mastery course.

External references: