Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Theory: Images and running containers

Docker is a set of tools and a platform for building, running, and sharing containers using the same ideas as the previous chapter. People often say “Docker container” to mean a container created and managed with Docker’s stack.

Image

An image is a read-only template. It contains a filesystem snapshot (your app, libraries, config files) and metadata (which command to run, environment defaults, exposed ports).

Images are built in layers. Each step in a build adds a layer. Layers can be reused across images, which saves space and speeds pulls.

You pull images from a registry (Docker Hub, ECR, GHCR, a private registry) or build them locally.

Container

A container is a running instance of an image. It gets a thin writable layer on top of the image layers. When the container stops, that writable layer can be discarded unless you commit it (uncommon in production workflows).

One image can start many containers. Each container has its own process ID space, network setup, and filesystem view as configured at run time.

Simple flow and lifecycle

Two common paths get an image onto your machine. You either pull an image someone else published, or you build from a Dockerfile and build context on your machine. In both cases you end up with a local image in Docker’s storage.

Run creates a container from that image and starts the main process. While it runs, the app reads the image layers and writes to the thin writable layer. Stop ends the process. The container object can stay on disk until you remove it. Remove deletes the container. Removing an image is a separate step (docker rmi) and only affects the read-only template, not other containers still using other tags of the same repository.

flowchart LR
    subgraph obtain["Get an image"]
        P["docker pull"]
        B["docker build"]
    end
    LI["Local image"]
    P --> LI
    B --> LI
    LI --> R["docker run"]
    R --> RUN["Container running"]
    RUN --> ST["docker stop"]
    ST --> OFF["Container stopped"]
    OFF --> RM["docker rm"]
    RM --> GONE["Container gone"]

Registry path when you do not build locally:

flowchart LR
    REG[("Registry")] -->|"docker pull"| IMG["Image on disk"]
    IMG -->|"docker run"| C["Container"]

These diagrams omit optional steps such as tag, push, and commit, which matter for CI and image promotion. Theory: Registry and image lifecycle picks up that story.

Commands you will see everywhere

These are the verbs most tutorials use. You do not need to memorize flags yet.

  • docker pull downloads an image from a registry.
  • docker run starts a container from an image (create + start).
  • docker build builds an image from a Dockerfile and build context.
  • docker ps lists running containers. docker images lists local images.

Compose

Docker Compose reads a YAML file (for example compose.yaml) and runs multiple containers together (web app, database, cache). It is a convenience layer on top of the same Engine API.

Security angle in one paragraph

Images are artifacts. If the image contains a vulnerable package or a leaked secret, every container started from it inherits that problem. Runtime flags (--privileged, bind mounts, extra capabilities) can widen what a container can do on the host. The rest of the workshop shows how to inspect and tighten both the image and the runtime.

Next: Theory: Dockerfile.