A Docker image is produced at build time and used at container runtime. Keeping those two phases separate makes Docker easier to reason about: the image is the packaged template, while the container is a running instance created from that template.

This note connects four related ideas: image build time, image layers, container runtime, and image tags.

Mental Model

flowchart LR
    Dockerfile["Dockerfile"] --> Build["docker build"]
    Context["Build context"] --> Build
    Base["Base image"] --> Build
    Build --> Image["Image: layers plus metadata"]
    Image --> Tag["Tag: my-api:1.0"]
    Image --> Run["docker run"]
    Run --> Container["Container runtime: process plus writable layer"]

Read it like this:

  1. Docker reads a Dockerfile and build context.
  2. Docker builds an image from instructions such as FROM, RUN, COPY, ENV, EXPOSE, and CMD.
  3. The image is stored as layers plus metadata.
  4. A tag gives the image a human-readable reference.
  5. docker run creates a container from the image.
  6. The container runs a process and adds its own writable layer.

Docker Image Lifecycle

The image lifecycle is the path an image takes from build to registry to runtime.

flowchart LR
    Source["Source code plus Dockerfile"] --> Build["docker build"]
    Build --> LocalImage["Local image"]
    LocalImage --> Tag["docker tag"]
    Tag --> Login["docker login"]
    Login --> Push["docker push"]
    Push --> Registry["Registry image"]
    Registry --> Pull["docker pull"]
    Pull --> Run["docker run"]
    Run --> Container["Container"]
    Container --> Stop["docker stop"]
    Stop --> RemoveContainer["docker rm"]
    LocalImage --> RemoveImage["docker rmi or prune"]

The important distinction:

StageObjectWhat Happens
BuildImageDocker creates local image layers and metadata
TagImage referenceDocker adds a human-readable name for the image
PushRegistry copyDocker uploads image layers and manifest to a registry
PullLocal imageDocker downloads image content from a registry
RunContainerDocker creates and starts a runtime instance from the image
Stop/removeContainerDocker stops or deletes the container, not the image
Remove/pruneImageDocker removes local image references/layers when unused

Key Insight: docker push shares an image through a registry. It does not start the application. docker run starts a container from an image.

Build Time

Build time is when Docker creates the image.

docker build -t my-api:1.0 .

In that command:

PartMeaning
docker buildRun the image build process
-t my-api:1.0Add the image tag my-api:1.0
.Use the current directory as the build context

The build uses:

InputRole
DockerfileBuild recipe
Build contextFiles available to COPY or ADD
Base imageStarting filesystem and metadata from FROM
Build argumentsOptional values available during build

The output is an image. The image is not running yet.

Key Insight: RUN happens during build time. CMD is saved as metadata for what should run later when a container starts.

Example:

FROM node:lts-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
CMD ["node", "server.js"]

During docker build, Docker runs npm ci --omit=dev and stores the result in the image. It does not run node server.js during the build. That command is the default runtime process.

Docker Image Layers

An image is a stack of read-only layers plus metadata.

my-api:1.0 image
 
+----------------------------------+
| CMD ["node", "server.js"]        | metadata
+----------------------------------+
| COPY . .                         | app files
+----------------------------------+
| RUN npm ci --omit=dev            | dependencies
+----------------------------------+
| COPY package*.json ./            | dependency manifests
+----------------------------------+
| WORKDIR /app                     | metadata
+----------------------------------+
| FROM node:lts-alpine             | base image layers
+----------------------------------+

Layers matter because Docker can reuse them.

If only application source changes, Docker may reuse the dependency install layer and rebuild only the later COPY . . layer. That is why Dockerfiles often copy dependency files first, install dependencies, then copy the rest of the application.

COPY package*.json ./
RUN npm ci --omit=dev
 
COPY . .

This is not just a performance trick. It also makes the image history easier to inspect:

docker image history my-api:1.0

Container Runtime

Container runtime is when Docker creates and starts a container from an image.

docker run --name api-1 -p 8080:3000 my-api:1.0

At runtime, Docker uses the image as the read-only base and adds runtime-specific state:

Runtime ItemExample
Main processnode server.js
Container nameapi-1
Writable layerFiles changed after the container starts
Environment overrides-e NODE_ENV=production
Port publishing-p 8080:3000
Volumes or mountsPersistent or host-provided files

The image remains unchanged.

running container
 
+----------------------------------+
| container writable layer         | changes after start
+----------------------------------+
| image layer: COPY . .            |
+----------------------------------+
| image layer: RUN npm ci          |
+----------------------------------+
| image layer: FROM node image     |
+----------------------------------+

If the app writes logs, cache files, uploads, or package installs inside the container filesystem, those changes belong to the container writable layer. They do not update my-api:1.0.

For the next step, see Container Changes and Image Updates.

Build Time vs Runtime

QuestionBuild TimeRuntime
Main commanddocker builddocker run
Main artifactImageContainer
File changes go toImage layersContainer writable layer, unless using mounts
Dockerfile instruction exampleRUN apt-get install ...CMD ["node", "server.js"]
Typical purposePackage app and dependenciesStart the app process
RepeatabilityShould be scripted in DockerfileShould be configured with run options or Compose

Image Tag

An image tag is a human-readable reference to an image.

registry.example.com/team/my-api:1.0
|------------------| |-------| |---|
      registry       repository  tag

Common examples:

docker build -t my-api:1.0 .
docker image tag my-api:1.0 registry.example.com/team/my-api:1.0
docker run my-api:1.0

docker tag is sometimes described as renaming an image, but it does not rewrite the image. It adds another reference to the same image content.

same image content
      |
      +-- my-api:1.0
      |
      +-- registry.example.com/team/my-api:1.0

If no tag is provided, Docker uses latest by default for many image references.

docker pull nginx

is treated like:

docker pull nginx:latest

Warning: latest does not mean newest, safest, or production-ready. It is just a tag name used by convention.

Tag vs Digest

Tags are convenient, but tags can move. A registry can make my-api:1.0 point to a different image later if someone pushes a new image with that same tag.

A digest identifies exact image content.

docker pull nginx@sha256:<digest>
Reference TypeExampleGood For
Tagmy-api:1.0Human-friendly versions and local development
latest tagnginx:latestQuick testing, not strong reproducibility
Digestnginx@sha256:<digest>Pinning exact image content
Image IDsha256:...Local inspection and debugging

For learning and local work, tags are fine. For reproducible production deployments, use deliberate version tags and consider digest pinning where exact content matters.

TL;DR

  • Build time creates an image.
  • Runtime creates and starts a container from that image.
  • Image layers are read-only and reusable.
  • A container adds a writable layer on top of image layers.
  • RUN changes the image during build; CMD defines the default runtime command.
  • A tag is a convenient name for an image, but a digest is the stronger reference for exact content.

Resources

Docker: What is an image? Official Docker explanation of images, immutability, and image layers.

Docker: Understanding image layers Official Docker guide for how image layers stack and how containers add writable changes.

Docker: Build, tag, and publish an image Official workflow for building and tagging images.

Docker CLI: docker image tag Official reference for image tag structure and examples.