Chapter 02Lesson 05~120 minutes

Checkpoint Lab — Installing Docker Engine and Desktop, CLI Basics, Daemon Connectivity, Contexts, and Environment Setup

Prove a disposable Docker environment end to end by capturing platform, distribution source, client/server/API, context/endpoint, data-root/storage baseline, privilege model, immutable test image, container identity, restart persistence, limitations, and exact cleanup in one reviewable evidence packet.

CheckpointEvidence packetContextPersistenceCleanup

Learning objectives

  • Capture platform, installation source, Docker client/server/API, context, plugin, and authorization evidence before creating resources.
  • Predict image/container/restart/cleanup state changes and verify each prediction independently.
  • Resolve the verification image to an immutable digest and bind it to the exact container object and exit evidence.
  • Restart a disposable Engine/Desktop boundary safely and prove which image/container metadata persists.
  • Deliver exact cleanup plus an assumptions/limitations note that distinguishes observed facts from platform abstractions.
Chapter 02 technical baseline — verified 2026-09-20. Docker Engine 29.8.1 and Docker Desktop 4.91.0 are current releases at this verification date. Current upstream Buildx, BuildKit, and Compose releases are 0.37.1, 0.33.0, and 5.5.1 respectively. Do not infer those exact bundled versions from the product name: every lab records the actual client/server/API/context/storage/component baseline first.

1. Checkpoint scenario and acceptance criteria

Establish one disposable Docker environment and prove it as if handing it to another engineer. The preferred execution path is a disposable native-Linux Engine host from Lesson 2; Docker Desktop learners may use the Desktop variant and mark host-service/data-root details that are abstracted by the VM as such.

Your evidence packet must answer: What platform is this? How was Docker obtained? Which client and server are in use? Which context/endpoint receives commands? What is the daemon data root/storage model? What privilege model lets this user administer Docker? Which immutable image content was tested? Which container object was created? What survived restart? What was cleaned up?

2. Setup and lab identity

set -eu

LAB_CONTAINER="da-ch02-checkpoint"
LAB_LABEL="devops-academy.lab=chapter02-checkpoint"
LAB_IMAGE_TAG="hello-world:latest"
EVIDENCE_DIR="$HOME/da-ch02-evidence"
mkdir -p "$EVIDENCE_DIR"

printf 'started=%s
' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" | tee "$EVIDENCE_DIR/session.txt"
Ownership guard. Do not proceed on a production/shared daemon. If docker context inspect shows an endpoint you do not explicitly own for this lab, stop. If unrelated running containers exist on a disposable VM you thought was empty, investigate before daemon restart.

3. Capture platform, client, server, context, and privilege preflight

{
  echo '=== host ==='
  uname -a 2>/dev/null || true
  uname -m 2>/dev/null || true
  cat /etc/os-release 2>/dev/null || true
  echo '=== client/server ==='
  docker version
  echo '=== context ==='
  docker context show
  docker context ls
  docker context inspect "$(docker context show)"
  echo '=== environment overrides ==='
  env | grep '^DOCKER_' || true
  echo '=== plugins ==='
  docker buildx version 2>/dev/null || true
  docker compose version 2>/dev/null || true
  echo '=== identity ==='
  id 2>/dev/null || true
  ls -l /var/run/docker.sock 2>/dev/null || true
} | tee "$EVIDENCE_DIR/preflight.txt"

On Windows/Desktop, save wsl --version and the Desktop version/backend separately. Never invent Linux service/socket evidence that your Desktop host cannot expose.

4. Capture daemon state, data root, storage, and security baseline

{
  docker info
  docker info --format 'DockerRootDir={{.DockerRootDir}}'
  docker info --format 'Driver={{.Driver}} CgroupVersion={{.CgroupVersion}} CgroupDriver={{.CgroupDriver}}'
  docker info --format 'SecurityOptions={{json .SecurityOptions}}'
} | tee "$EVIDENCE_DIR/daemon-baseline.txt"

Record the data root as an identity fact. Do not browse/delete its internals for this checkpoint. If Docker Desktop abstracts this behind the managed VM, record that boundary instead.

5. Write predictions before changing runtime state

Prediction Verification
Pulling the tag will create/reuse local image content on the selected daemon and resolve to a repository digest. docker image inspect and RepoDigests.
Running the digest will create one named, labeled container that exits successfully. Exact container ID, label, status, exit code, logs.
A daemon/Desktop restart will replace control-plane process state but preserve image and stopped-container metadata. Same image/container identity remains queryable after restart.
Removing the exact lab container will not remove unrelated images/volumes/networks. Label-filter returns no lab container; broader daemon state remains untouched.

6. Resolve the image and run the checkpoint container

docker pull "$LAB_IMAGE_TAG" | tee "$EVIDENCE_DIR/pull.txt"
IMAGE_REF="$(docker image inspect "$LAB_IMAGE_TAG" --format '{{index .RepoDigests 0}}')"
IMAGE_ID="$(docker image inspect "$LAB_IMAGE_TAG" --format '{{.Id}}')"
printf 'image_ref=%s
image_id=%s
' "$IMAGE_REF" "$IMAGE_ID" | tee "$EVIDENCE_DIR/image.txt"

docker run --name "$LAB_CONTAINER" --label "$LAB_LABEL" "$IMAGE_REF"   | tee "$EVIDENCE_DIR/container-output.txt"

docker inspect "$LAB_CONTAINER" >"$EVIDENCE_DIR/container-inspect.json"
docker inspect "$LAB_CONTAINER" \
  --format   'id={{.Id}} image={{.Image}} status={{.State.Status}} exit={{.State.ExitCode}} labels={{json .Config.Labels}}'   | tee "$EVIDENCE_DIR/container-summary.txt"

A successful exit is useful evidence, but write explicitly that it does not prove port publication, application health, persistent data, or registry publication.

7. Preflight the restart

docker ps --format 'table {{.ID}}	{{.Names}}	{{.Status}}'
docker ps -a --filter "label=$LAB_LABEL"

BEFORE_CONTAINER_ID="$(docker inspect "$LAB_CONTAINER" --format '{{.Id}}')"
BEFORE_IMAGE_ID="$(docker image inspect "$IMAGE_REF" --format '{{.Id}}')"
BEFORE_ROOT="$(docker info --format '{{.DockerRootDir}}')"
printf '%s
'   "before_container=$BEFORE_CONTAINER_ID"   "before_image=$BEFORE_IMAGE_ID"   "before_root=$BEFORE_ROOT"   | tee "$EVIDENCE_DIR/before-restart.txt"

If this command reveals unrelated running containers on a native Engine host, do not restart that daemon for the course exercise.

8. Restart safely and verify persistence

Native Linux Engine path:

sudo systemctl restart docker
sudo systemctl is-active docker

Docker Desktop path: use Docker Desktop's supported restart control/CLI for your installed release. Do not kill VM processes manually. After Desktop is healthy again, continue with portable Docker CLI checks below.

docker version
docker context show

AFTER_CONTAINER_ID="$(docker inspect "$LAB_CONTAINER" --format '{{.Id}}')"
AFTER_IMAGE_ID="$(docker image inspect "$IMAGE_REF" --format '{{.Id}}')"
AFTER_ROOT="$(docker info --format '{{.DockerRootDir}}')"

printf '%s
'   "after_container=$AFTER_CONTAINER_ID"   "after_image=$AFTER_IMAGE_ID"   "after_root=$AFTER_ROOT"   | tee "$EVIDENCE_DIR/after-restart.txt"

test "$BEFORE_CONTAINER_ID" = "$AFTER_CONTAINER_ID"
test "$BEFORE_IMAGE_ID" = "$AFTER_IMAGE_ID"

The checkpoint is about evidence, not forcing every platform into identical internals. A Desktop learner can prove Docker object persistence without claiming access to the managed VM's systemd process state.

9. Document how this user is authorized to Docker

Choose the statement that matches your environment and attach evidence:

Observed mode Evidence Security interpretation
Explicit sudo Non-sudo denied or unused; sudo docker version succeeds. Elevation is explicit per command.
docker-group socket access id, group membership, socket ownership. User effectively has root-level daemon control; document as privileged access.
Rootless docker info security options/context/socket plus subordinate-ID readiness. Daemon itself runs unprivileged; different endpoint/data paths and limitations apply.
Desktop-managed user access Desktop/context/host permission model. Daemon lives behind Desktop's managed VM/backend and permission mediation.

10. Required evidence packet

Platform

OS/release, architecture, kernel or Desktop backend prerequisites.

Distribution source

Docker repository/Desktop release/manual path and exact package/application versions.

Client/server

Docker CLI, Engine server, negotiated API, Buildx/Compose versions.

Target identity

Context name and endpoint; any DOCKER_* overrides.

Persistent daemon state

Data root, storage driver/image store evidence, image ID/digest.

Runtime proof

Container ID, status/exit, logs, labels, before/after restart identity.

Privilege model

sudo, docker group, rootless, or Desktop-mediated access with limitations.

Limitations

What was not observed, what the hello-world check does not prove, and any platform abstraction.

11. Exact cleanup and rollback

docker inspect "$LAB_CONTAINER" --format 'name={{.Name}} labels={{json .Config.Labels}}'
docker rm "$LAB_CONTAINER"
docker ps -a --filter "label=$LAB_LABEL"

printf 'finished=%s
' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" | tee -a "$EVIDENCE_DIR/session.txt"

Do not uninstall Docker or delete the data root unless the entire VM itself is the disposable lab artifact and you intentionally destroy/rebuild the VM. The evidence directory is intentionally outside the Docker data root so it survives container cleanup.

12. Explain every successful state precisely

Observed success What it proves What it does not prove
docker version has Client and Server Selected client can reach an Engine and negotiate an API. Correct context for your intended environment unless endpoint was verified.
Image has repository digest Registry content identity was resolved and is locally known. Image is vulnerability-free or trusted for production.
Container exited 0 Main process ran and returned success on that daemon. Application readiness, network exposure, persistent data, or external system health.
Same container/image ID after restart Persistent Docker metadata/content survived control-plane restart. Every running workload would survive or resume automatically.
Cleanup label filter empty No container with the lab ownership label remains. No unrelated Docker resources were changed; preserve command history/evidence for that claim.

Knowledge check

Why must the checkpoint record the active context even on a “local” developer machine?

Why is a repository digest stronger checkpoint evidence than only hello-world:latest?

What does unchanged container ID after daemon restart demonstrate?

If the evidence packet says “docker group access,” what security note is mandatory?

Why is “Desktop VM internals not directly observed” acceptable evidence on Docker Desktop?

13. Chapter 02 operational review

You can now install and verify Docker without collapsing software source, client, daemon, endpoint, Desktop VM, persistent data, privilege, and workload state into one checkbox. You can show where the packages or Desktop application came from, which server a client controls, how state survives restart, and why convenience access can expand privilege.

Chapter 03 moves inside the Engine boundary: dockerd, containerd, runc, BuildKit, APIs, and the container lifecycle. The version/context/data-root baseline you created here becomes the evidence foundation for understanding those components without guessing at implementation details.

Next chapter

Next: Docker Engine Components: dockerd, containerd, runc, BuildKit, APIs, and Container Lifecycle: Concepts, Architecture, and Mental Model

Continue with the next lesson in the course sequence and carry forward the evidence-first Docker operating model.

Official references and version notes

Version-sensitive statements in this chapter were rechecked against primary documentation on 2026-09-20. Installation support, package names, Desktop requirements, component versions, context behavior, rootless prerequisites, and security guidance evolve. Always record the versions and platform facts actually reported by the environment you are operating.

Current baseline, not a frozen requirement

At this chapter's verification date, Docker Engine 29.8.1 and Docker Desktop 4.91.0 are current releases, while Buildx 0.37.1, BuildKit 0.33.0, and Compose 5.5.1 are current upstream releases. Bundled component versions can differ by Engine/Desktop/package source. Use docker version, docker info, docker buildx version, and docker compose version as execution evidence rather than assuming those upstream versions are installed.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.