Skip to content

What is Docker?

Docker is not a single program — it is an ecosystem of components that work together. Understanding each piece makes it much easier to reason about what happens when you run a docker command.

The docker CLI is the program you interact with directly. When you type a command such as docker run, docker build, or docker pull, the CLI translates that instruction into a REST API request and forwards it to the Docker daemon. The client itself does no heavy lifting — it is a thin API client.

The client communicates with the daemon over a Unix socket at /var/run/docker.sock by default. For remote daemons (for example, a Docker host running on a cloud VM), the client can connect over TCP with TLS.

The daemon is the long-running background process that does the actual work. It listens on the Unix socket (or TCP port) and handles every API call the client sends. The daemon is responsible for:

  • Pulling and caching images from registries.
  • Creating and running containers from those images.
  • Managing networks so containers can communicate with each other and with the outside world.
  • Managing volumes for persistent data that outlives a container’s lifetime.

An image is a read-only, layered package that contains everything needed to run a process: the application code, a base OS filesystem, runtime libraries, environment variables, and the default command to execute. Images are built from a Dockerfile and are identified by a name and tag such as nginx:1.27-alpine.

Each layer in an image represents a single instruction in the Dockerfile. Layers are cached and shared across images, which keeps disk usage low and rebuilds fast.

A registry is a server that stores and distributes images. The default public registry is Docker Hub (docker.io). When you run docker pull nginx, the daemon contacts docker.io, finds the nginx repository, and downloads the image to the local cache.

Registries organise images into repositories. A repository can hold many versions of the same image, distinguished by tags:

flowchart TB
  ref["docker.io/library/nginx:1.27-alpine"]
  ref --> host["registry host: docker.io"]
  ref --> ns["namespace: library (official images)"]
  ref --> repo["repository name: nginx"]
  ref --> tag["tag: 1.27-alpine"]
Anatomy of an image reference

Private registries (Amazon ECR, GitHub Container Registry, a self-hosted registry) work the same way — you just docker login to authenticate before pushing or pulling.

The flow every docker run command follows:

flowchart TB
  you["You (terminal): docker run nginx"]
  cli["docker CLI"]
  daemon["dockerd (daemon)"]
  registry["Docker Hub (or other registry)"]
  cache["Local image cache"]
  container["Running container (isolated process on host kernel)"]
  you --> cli
  cli -->|REST API over Unix socket| daemon
  daemon -->|Image not in local cache| registry
  registry -->|Pull image layers| cache
  cache -->|Create container from image| container
What happens when you run docker run
  1. You type docker run nginx.
  2. The CLI sends a POST /containers/create request to dockerd over the Unix socket.
  3. dockerd checks the local image cache for nginx:latest.
  4. If the image is absent, dockerd contacts Docker Hub, authenticates if needed, and pulls the image layers.
  5. The layers are stored in the local cache (typically under /var/lib/docker).
  6. dockerd creates a new container from the image and starts the process.
  7. Standard output from the container is streamed back through dockerd to your terminal via the CLI.
What is the role of the Docker daemon (`dockerd`)?
Where does the Docker CLI send its commands by default?
What is a Docker image?
In the image reference `docker.io/library/nginx:1.27-alpine`, what does `1.27-alpine` represent?