Which image a container runs
The first inspect field is the name the container was created with, the
second is the image ID. If the name has since moved to a new image, the ID
tells.
An image is a read-only stack of layers with files and run settings; Docker creates containers from it.
sudo docker load -i /opt/images/alpine.tar
image from a file
sudo docker images
images on this machine
sudo docker image ls --digests
with digests
sudo docker history nginx:alpine
layers and what made them
sudo docker image inspect -f '{{.Id}}' busybox
full ID
sudo docker tag busybox:latest app:1.0
a second name, same image
sudo docker rmi app:1.0
drop a tag or the image
sudo docker image prune
remove untagged images
sudo docker save busybox > busybox.tar
image to a file
sudo docker pull nginx:alpine
fetch from a registry (network)
An image is the template Docker creates containers from. It holds the container's files — the program, libraries, configs — and its run settings: command, environment variables, working directory, port. An image never changes. A container writes to its own layer on top of the image, so one image can back any number of containers.
The lab machine has no outside network. Images sit as files in
/opt/images, and docker load brings them into Docker. Here student is
not in the docker group, so every command goes through sudo.
| Column | What it shows |
|---|---|
| IMAGE | image name: repository and tag |
| ID | short ID — the first 12 characters of the hash |
| CONTENT SIZE | compressed layers, as in the file or the registry |
| DISK USAGE | space on disk including unpacked layers |
| EXTRA | U — at least one container uses the image |
After the table docker images prints a warning, This output is designed
for human readability: the table layout may change between Docker
versions. Scripts need --format — see the recipe below.
A registry is a server that stores images: Docker Hub, GitLab
Registry, a company registry. docker pull downloads an image from it,
docker push uploads one. The full image name says where it lives:
With no registry in the name Docker goes to Docker Hub; with no tag it
takes latest. nginx:alpine means docker.io/library/nginx:alpine. The
full name shows up in the error when the image is missing:
failed to resolve reference "docker.io/library/nginx:alpine".
An image is built from layers. A layer is an archive
of file changes: what was added, changed or deleted relative to the layers
below. Every dockerfile instruction that changes files produces a
layer. docker history lists them, newest first:
The bottom row is the Alpine layer: nginx:alpine is built on top of the
Alpine image. Rows of size 0B (CMD, EXPOSE, ENV) change no files —
they record run settings. <missing> in the IMAGE column means the step
has no separate image on this machine; every pulled or loaded image looks
like this.
Identical layers are stored once. Ten images based on Alpine keep a single copy of its layer on disk.
Image layers are read-only. A container gets its own writable layer on top — the container layer. A file changed inside the container is copied up into that layer (copy-on-write); the image stays as it was.
The container layer lives as long as the container: docker stop and
docker start keep it, docker rm deletes it with all its data. Data that
must survive re-creating a container goes into a volume — see
Volumes in the Docker article.
A tag is a movable name: the part after the colon.
docker tag gives the same image a second name; both names share one ID:
latest is just the default tag. It is used when no tag is given and says
nothing about freshness: alpine:latest on this machine is whatever image
was loaded into it.
A tag moves on rebuild. A second docker build -t app:1.1 hands the name
to the new image, and the old one is left nameless, <none>:<none> — a
dangling image. Plain docker images hides it; a filter finds it:
docker images -a lists such images as <untagged>.
docker rmi <name> removes a tag. If the image has other names, it stays:
Untagged: busybox:latest. For the last name docker rmi deletes the
image too — as long as no container needs it.
A digest is the SHA-256 of the image manifest, the
description of its layers and settings. Change a single byte in any layer
and the digest changes. So nginx@sha256:1acb… always means the same
content, while nginx:alpine may point to a different image tomorrow.
In Docker 29 images are stored by containerd, and a loaded image's ID is the same as its digest.
docker save writes an image with all its layers to a tar archive;
docker load reads it back — on this machine or another one. That is how
an image reaches a host with no registry access. The archive uses the OCI
layout: index.json, manifest.json and a blobs/sha256 directory where
every file is named after its own SHA-256.
The first inspect field is the name the container was created with, the
second is the image ID. If the name has since moved to a new image, the ID
tells.
index.json points to the manifest by digest, the manifest file is named
with that digest, and sha256sum of it gives the same number. Registries
and Docker use these hashes to check that a layer arrived intact.
No image with that name and tag is on the machine, so Docker went to the
registry for it. docker run, docker build with such a FROM, and
docker compose up all do this. Without network the request fails on
lookup registry-1.docker.io. Compare the name and tag with
docker images (busybox:latest and busybox:1.36 are different images)
or load the image from a file with docker load -i.
A container needs the image, even a stopped one. Find it with
docker ps -a --filter ancestor=busybox, remove it with docker rm, then
the image.
A container is created from the image that held the name at docker run
time. A new build under the same tag does not touch it. Re-create the
container: docker rm -f web, then docker run with the same options.
Compare IDs: docker inspect -f '{{.Image}}' web and
docker image inspect -f '{{.Id}}' app:1.1.
<none> instead of a nameDangling images remain after rebuilding under the same tag. They take
space but do no harm. Clean up with docker image prune.
sudo docker save -o file.tar creates the file as root with mode 600,
and student cannot read it. Redirect the output instead —
sudo docker save busybox > busybox.tar: your shell creates the file, so
it is yours.
prune -a removes dangling images and every other image that no container
needs right now. Without network there is nothing to pull them back from:
you have to find the file for docker load again. rmi -f lifts the
guard against deleting an image a container needs.
image: app:latest in compose or a start script means "whatever is under
that name now". After docker pull or a new build the service quietly
comes up on another version. Pin a version tag or a digest:
nginx@sha256:1acb5b02….
inspect.docker save archive format.Found an inaccuracy? Report an error in the article