Images and layers
What an image contains, how layers and the build cache work, and how to ship only what runs.
An image is layers plus a configuration
An image has two parts. The first is an ordered list of layers, each a tarball of filesystem changes. The second is a configuration: entrypoint and command, environment variables, working directory, user, exposed ports, and labels. When a container starts, the runtime stacks the layers into one read-only root filesystem, adds a thin writable layer for that container, and starts the configured process. Container Security describes the format and the OCI standards behind it. Operationally, three facts follow:
- Each build step adds a layer, and later steps cannot remove bytes from earlier layers, only hide them.
- The configuration is part of the image.
USER,ENV, andENTRYPOINTtravel with it and can be inspected withdocker image inspect. - Anything in any layer can be extracted by anyone who can pull the image. A secret added in step 3 and deleted in step 4 is still published.
The build cache rewards good ordering
Each step's cache key depends on the step itself and on the files it reads. When something changes, that step and every step after it rebuild. A Dockerfile ordered for caching goes from what changes least to what changes most:
FROM node:22-slim AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build && npm prune --omit=dev
Dependencies reinstall only when the lockfile changes, and source edits rebuild only the last two steps.
Ship only what runs
The image built above still contains npm's cache, development tooling, and source. A multi-stage build starts a clean final stage and copies only the result:
FROM node:22-slim
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
USER node
CMD ["node", "dist/server.js"]
Smaller images move faster through registries and node pulls, start faster, and contain fewer packages that a scanner will flag or an attacker can use. A .dockerignore file keeps .git, local environment files, and build outputs out of the build context to begin with.
Tags are names, digests are identities
waybill:2.4 is a tag, a mutable pointer in a registry, just like a Git branch. waybill@sha256:3f1c… is a digest, the hash of the image manifest, and it can never refer to different content. Twelve-Factor's separation of build, release, and run depends on it. You build once, and every environment runs the identical artifact. Promote by digest, record the digest in the release, and the question "what is running?" has an exact answer. The Continuous Delivery track builds the pipeline around this.
Inspect before you ship
docker image ls waybill
docker history waybill:candidate # layer sizes and the step that created each
docker image inspect waybill:candidate --format '{{.Config.User}} {{json .Config.Entrypoint}}'
docker history points straight at the layer that carries a compiler or a cache. The lab gives you a 1.3 GB image and a size budget. Find the heavy layers and rebuild until the runtime image carries only what runs.
Key terms
- Layer
- A filesystem diff produced by one build step. Layers are stacked read-only, and a container adds one writable layer on top.
- Build cache
- Reuse of a previous layer when a step and all of its inputs are unchanged. Changing one step invalidates every step after it.
- Multi-stage build
- A Dockerfile with several
FROMstages. Later stages copy only selected files from earlier ones. - Digest
- The content hash of an image manifest (
sha256:…). Unlike a tag, it can never point at something else.
Read further
- Container Security, Chapter "Container Images" (Purchase)
The root filesystem and image configuration, the OCI standards, how images are built and stored, and the risks of sensitive data baked into layers. - UNIX and Linux System Administration Handbook, 5th edition, Ch. 25, "Containers" (Purchase)
The Docker sections on images, Dockerfiles, and registries. Compare its account of layers with the Container Security chapter. - The Twelve-Factor App, Factors II "Dependencies" and V "Build, release, run" (Free online)
Why dependencies are declared and isolated, and why the build stage is separate from the release and run stages. The image is the build artifact.