Checkpoint Lab — Bind Mounts, Read-Only Mounts, tmpfs, Mount Propagation, Subpaths, SELinux Labels, and Host Coupling
Build a mount-security matrix for read-only bind, writable bind, and tmpfs; verify side effects and lifetime; then remove only exact disposable resources.
Learning objectives
- Create a three-way mount-security matrix for read-only bind, writable bind, and tmpfs.
- Predict and verify which operations can change host files and which state disappears with the container.
- Capture source/target/RW/propagation, context, ownership, tmpfs, and host-side checksum evidence.
- Prove cleanup removes only exact lab containers, volume, and disposable paths without broad filesystem operations.
- Summarize what host coupling adds to the production Docker threat and portability model.
1. Setup and assumptions
The mandatory path uses a local Engine or Docker Desktop, BusyBox, ordinary bind mounts, and tmpfs. No paid feature, remote registry, privileged mode, SELinux disablement, daemon change, or production path is required.
docker version
docker info
docker context show
docker compose version || true
docker buildx version || true
docker ps -a --no-trunc
docker volume ls
docker pull busybox:1.36.1
rm -rf da21-checkpoint
mkdir -p da21-checkpoint/ro-src da21-checkpoint/rw-src da21-checkpoint/evidence
printf 'RO-ORIGINAL
' > da21-checkpoint/ro-src/config.txt
printf 'RW-ORIGINAL
' > da21-checkpoint/rw-src/state.txt
sha256sum da21-checkpoint/ro-src/config.txt da21-checkpoint/rw-src/state.txt | tee da21-checkpoint/evidence/host-before.sha256
docker context inspect "$(docker context show)" --format '{{json .Endpoints.docker.Host}}' | tee da21-checkpoint/evidence/context-endpoint.txt
2. Make predictions before execution
| Prediction | Expected state change |
|---|---|
| RO bind | Container reads host config; attempted write fails; host checksum remains unchanged. |
| RW bind | Container appends/creates files; host checksum and directory inventory change. |
| tmpfs | Container creates ephemeral file; no bind source exists; file is absent in a replacement container. |
| Container removal | Removes container objects only; bind source files remain on host. |
Write these predictions into
da21-checkpoint/evidence/predictions.txt in your own
words before running the matrix.
3. Matrix A — read-only bind
docker run -d \
--name da21-cp-ro \
--label devops-academy.lab=ch21-checkpoint \
--mount type=bind,src="$(pwd)/da21-checkpoint/ro-src",dst=/data,readonly busybox:1.36.1 sleep 300
docker inspect da21-cp-ro --format '{{json .Mounts}}' | tee da21-checkpoint/evidence/ro-mount.json
docker exec da21-cp-ro cat /data/config.txt | tee da21-checkpoint/evidence/ro-read.txt
if docker exec da21-cp-ro sh -c 'echo should-fail > /data/write.txt' >da21-checkpoint/evidence/ro-write.stdout 2>da21-checkpoint/evidence/ro-write.stderr; then
echo 'unexpected write success' >&2
else
echo 'read-only write blocked' | tee da21-checkpoint/evidence/ro-write-result.txt
fi
4. Matrix B — writable bind
docker run -d --name da21-cp-rw --label devops-academy.lab=ch21-checkpoint --mount type=bind,src="$(pwd)/da21-checkpoint/rw-src",dst=/data busybox:1.36.1 sleep 300
docker inspect da21-cp-rw --format '{{json .Mounts}}' | tee da21-checkpoint/evidence/rw-mount.json
docker exec da21-cp-rw sh -c '
printf "RW-CONTAINER-APPEND
" >> /data/state.txt
printf "CREATED
" > /data/generated.txt
ls -ln /data
' | tee da21-checkpoint/evidence/rw-container.txt
cat da21-checkpoint/rw-src/state.txt
cat da21-checkpoint/rw-src/generated.txt
ls -ln da21-checkpoint/rw-src | tee da21-checkpoint/evidence/rw-host.txt
5. Matrix C — tmpfs
docker run -d \
--name da21-cp-tmpfs \
--label devops-academy.lab=ch21-checkpoint \
--memory 64m \
--mount type=tmpfs,dst=/runtime,tmpfs-size=1048576,tmpfs-mode=1770 busybox:1.36.1 sh -c 'echo TMPFS-ONLY > /runtime/value.txt; sleep 300'
docker inspect da21-cp-tmpfs --format '{{json .Mounts}}' | tee da21-checkpoint/evidence/tmpfs-mount.json
docker exec da21-cp-tmpfs sh -c 'cat /runtime/value.txt; df -h /runtime; ls -ldn /runtime' | tee da21-checkpoint/evidence/tmpfs-live.txt
docker rm -f da21-cp-tmpfs
docker run \
--rm \
--mount type=tmpfs,dst=/runtime,tmpfs-size=1048576,tmpfs-mode=1770 busybox:1.36.1 sh -c 'test ! -e /runtime/value.txt && echo fresh-tmpfs-is-empty' | tee da21-checkpoint/evidence/tmpfs-replacement.txt
6. Verify predicted host effects
sha256sum da21-checkpoint/ro-src/config.txt da21-checkpoint/rw-src/state.txt | tee da21-checkpoint/evidence/host-after.sha256
find da21-checkpoint/ro-src da21-checkpoint/rw-src -maxdepth 1 -type f -printf '%p
' 2>/dev/null | sort | tee da21-checkpoint/evidence/host-files.txt || true
# Portable fallback if find -printf is unavailable:
ls -la da21-checkpoint/ro-src da21-checkpoint/rw-src | tee da21-checkpoint/evidence/host-listing.txt
The RO source checksum should match its original value. The writable
source should differ because the container intentionally appended
content, and generated.txt should be host-visible.
7. Record ownership and platform limitations
ls -ln da21-checkpoint/ro-src da21-checkpoint/rw-src | tee da21-checkpoint/evidence/ownership.txt
docker info --format '{{json .OperatingSystem}} {{json .OSType}} {{json .SecurityOptions}}' | tee da21-checkpoint/evidence/platform.txt
command -v getenforce >/dev/null && getenforce | tee da21-checkpoint/evidence/selinux.txt || true
Add an assumptions note explaining whether the daemon is native Linux or Docker Desktop, whether SELinux is active, whether UID/GID mapping is meaningful on this host, and whether propagation could be tested. If using a remote context, do not run the bind-mutating checkpoint against an unprepared remote host.
8. Inventory exact lab resources before cleanup
docker ps -a --filter label=devops-academy.lab=ch21-checkpoint --no-trunc | tee da21-checkpoint/evidence/containers-before-cleanup.txt
docker inspect da21-cp-ro da21-cp-rw --format '{{.Name}} {{json .Mounts}}' | tee da21-checkpoint/evidence/final-mounts.txt
9. Exact cleanup and rollback
docker rm -f da21-cp-ro da21-cp-rw da21-cp-tmpfs 2>/dev/null || true
docker ps -a --filter label=devops-academy.lab=ch21-checkpoint --no-trunc
# Preserve da21-checkpoint/evidence until review is complete.
# Then delete only the disposable da21-checkpoint directory with your normal host file manager/shell.
Cleanup intentionally does not use any broad Docker prune command or broad host filesystem deletion. The changed host files are evidence of the writable bind and should be reviewed before removal.
10. Required evidence packet
| Evidence | What it proves |
|---|---|
| Engine/context/version output | Which daemon/platform interpreted the mount configuration |
| RO/RW/tmpfs inspect JSON | Type, source, target, RW state, and propagation |
| Before/after checksums | Which host-backed content changed |
| RO write failure | Read-only policy enforced |
| RW host-visible files | Writable bind side effect reached host |
| tmpfs replacement output | Ephemeral data did not survive container replacement |
| Ownership/SELinux assumptions | Permission and LSM context needed to interpret results |
| Exact resource inventory | Cleanup scope is bounded |
11. What Chapter 21 adds to the production operating model
You can now reason about host-coupled storage as a security and portability boundary: identify the daemon host, narrow the source, default to read-only where possible, understand numeric ownership and SELinux, avoid unnecessary propagation, use tmpfs for bounded ephemeral state, and keep Docker-managed volumes for persistent data that should not depend on a particular host path.
Chapter 22 moves from storage authority to resource authority: CPU, memory, PID, device, ulimit, and cgroup governance. The same evidence-first habit applies—declare limits, observe actual runtime state, and distinguish host capacity from container policy.
Knowledge check
Which checkpoint mount should alter host file checksums?
Only the writable bind. The read-only bind should preserve its source, and tmpfs has no host filesystem source.
What proves tmpfs lifetime in the checkpoint?
The first container can read the tmpfs file, but a replacement container with a new tmpfs does not contain it.
Why is the active Docker context part of mount evidence?
Because the selected daemon host resolves bind source paths; the same client command can target a different filesystem on another context.
Why keep the evidence directory until after cleanup review?
The changed files, mount JSON, checksums, and errors prove the security matrix and help detect unexpected side effects before deletion.
What is the safest production default for host coupling?
Avoid it when not required; when it is required, mount the smallest path with the least write authority and explicit platform/security assumptions.
Official references and version notes
-
Docker Docs — Bind mounts
— daemon-host paths, read-only mode,
--mountversus-v, recursive mounts, propagation, and SELinux labeling. - Docker Docs — tmpfs mounts — memory-backed lifetime, size/mode options, and cgroup memory accounting.
- Docker CLI — docker container run — mount and read-only-root-filesystem semantics.
-
Compose Specification — service volumes
— bind options,
create_host_path, SELinux labels, tmpfs, and volume subpaths. -
Docker Docs — Volumes
—
volume-subpathas a mount-type-specific subpath feature and contrast with bind mounts. - Docker Desktop — File sharing — host-to-VM sharing boundaries and performance guidance.
- Docker Desktop — Synchronized file shares — optional paid synchronized host-file caching for large repositories.
-
Docker Engine 29 release notes
— current Engine baseline and
bind-create-srcaddition in 29.3.
Docker Engine 29.8.1 and Docker Desktop 4.91.0 are current; Compose 5.5.1, Buildx 0.37.1, and BuildKit 0.33.0 are the upstream baselines used for compatibility discussion. The labs record the learner's actual versions because host kernel, Docker Desktop VM/file-sharing mode, SELinux, and remote-context topology materially affect mount behavior.
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.