CertGrid CertGrid
Concepts·Docker

Docker Containers, Images, Registries and Daemon

The four things every later guide assumes you understand, each demonstrated with a command rather than a diagram: why the client and daemon are separate, how an image differs from a container, what a registry actually stores, and where a digest comes from.

Getting Started Guide 2 of 46 Beginner

Tested on the versions above. Image IDs, digests, sizes and creation timestamps change every time an image is rebuilt upstream. Match the shape of the output, not the exact strings.

One Docker host is all this guide needs. Nothing here depends on a second machine, and the hardware above is modest on purpose - a 2 core, 4 GB VM runs everything in this path.
Server NameIP AddressOSRolesCPURAMHDD
DOCKER01192.168.0.21Ubuntu 26.04 LTSDocker Host2 Core4 GB50 GB

Before you start

  1. The client and the daemon are two different programs

    docker is a command-line client. It does almost nothing itself - it sends API requests to a background service called dockerd, which does the actual work of pulling images and running containers. This is why the version command reports two versions, and why a permission error on the socket stops everything: you are being refused access to the daemon, not to the CLI.

    bash Example session
    docker version --format "Client {{.Client.Version}} / Server {{.Server.Version}} / API {{.Server.APIVersion}}"Client 29.7.2 / Server 29.7.2 / API 1.55

    Expected resultTwo version numbers and an API version. They are usually the same on one machine, but they do not have to be.

    Success conditionYou get both a Client and a Server version. If Server is missing, the daemon is not running or you cannot reach it - systemctl is-active docker will tell you which.

  2. An image is a read-only template; a container is a running instance of it

    This is the distinction that trips up nearly everyone. An image is a stack of read-only filesystem layers plus metadata. It never runs and never changes. A container is that stack plus a thin writable layer on top and a process. One image can back a hundred containers, and removing a container does not touch the image it came from.

    bash Example session
    docker image inspect nginx:alpine --format "layers={{len .RootFS.Layers}} size={{.Size}}"layers=8 size=26279045

    Expected resultA layer count and a size in bytes. Eight layers means eight stacked filesystem diffs.

    Success conditionYou get a layer count. Those layers are shared: pulling a second image built on the same base reuses them instead of downloading again, which is why the second pull is usually much faster.

  3. A registry stores images; a digest identifies exactly one

    A registry is a content-addressed store for images. Docker Hub is the default. Notice what the pull prints: a Digest: line. A tag such as 3.22 is a mutable label that can be repointed at a new build, but the digest is a hash of the content itself, so it always refers to one exact image. When something works on your machine and not on the server, comparing digests rather than tags is how you prove they are running different things.

    bash Example session
    docker pull alpine:3.223.22: Pulling from library/alpineDigest: sha256:14358309a308569c32bdc37e2e0e9694be33a9d99e68afb0f5ff33cc1f695dceStatus: Downloaded newer image for alpine:3.22docker.io/library/alpine:3.22

    Expected resultA digest and the fully qualified name. alpine:3.22 is shorthand - the real name is docker.io/library/alpine:3.22.

    Success conditionYou see a Digest: line. Run the same pull twice and the second reports Image is up to date instead of downloading.

  4. Where the pieces meet

    Listing images shows the store side. Listing containers shows the running side. Two rows here share a repository and tag but have different IDs - that is a tag being repointed at a newer build while the older image stays on disk, which is exactly the ambiguity digests exist to remove. Output is abridged to the first few rows.

    bash Example session
    docker image ls --format "table {{.Repository}}:{{.Tag}}\t{{.ID}}\t{{.Size}}"REPOSITORY:TAG       IMAGE ID       SIZEnginx:alpine         db35bfc6b295   94.2MBnginx:alpine         4a73073bd557   93.6MBalpine:latest        28bd5fe8b56d   13MBhello-world:latest   5dd0d3e6e255   25.9kB

    Expected resultOne row per image. Sizes are the on-disk size of the image, not the download size.

    Success conditionYou can see images listed independently of containers. docker ps -a lists containers - the two are separate stores and separate commands.

Troubleshooting

Official sources