Volumes, Named Volumes, Volume Drivers, Backup/Restore, Sharing, and Persistent Data Patterns: Guided Hands-On Workflow and Core Operations
Create, inspect, share, back up, restore, verify, and remove disposable named volumes while proving that container replacement does not equal data replacement.
Learning objectives
- Create and inspect a labeled named volume with the local driver and record its exact metadata.
- Prove data survives replacement of the container that originally wrote it.
- Use sequential helper containers to share the same data without assuming concurrent-write safety.
- Create a tar backup plus SHA-256 checksum, restore it into a different named volume, and verify content and metadata.
- Remove only exact disposable resources after proving no remaining lab dependency exists.
da20-, and a local
./da20-backup directory. No database, secret, production
path, plugin, daemon mutation, or broad prune operation is required.
1. Preflight, workspace, and evidence
Create a dedicated workspace and record the active engine/context before creating storage. The volume label provides an ownership guard for later inventory.
docker version
docker info
docker context show
docker compose version || true
docker buildx version || true
docker volume ls
docker ps -a --no-trunc
docker pull busybox:1.36.1
docker image inspect busybox:1.36.1 --format 'ID={{.Id}} RepoDigests={{json .RepoDigests}}'
mkdir -p da20-lab/da20-backup da20-lab/evidence
cd da20-lab
docker volume ls --filter label=devops-academy.lab=ch20
docker ps -a --filter label=devops-academy.lab=ch20
2. Create and inspect the named volume
The local driver is selected explicitly even though it
is the default. The label does not affect data; it expresses lab
ownership.
docker volume create --driver local --label devops-academy.lab=ch20 --label devops-academy.purpose=primary-data da20-data
docker volume inspect da20-data | tee evidence/volume-before.json
docker volume inspect da20-data \
--format 'Name={{.Name}} Driver={{.Driver}} Scope={{.Scope}} Mountpoint={{.Mountpoint}} Options={{json .Options}} Labels={{json .Labels}}'
On Docker Desktop, the mountpoint shown by the daemon belongs to Docker's managed Linux environment, not necessarily to a path you should browse from the desktop host. Treat it as evidence, not as the supported data-management interface.
3. Write synthetic state through a container mount
Use long --mount syntax so source and target are
unambiguous. Record both a logical version marker and a data file.
docker run --rm --name da20-writer --label devops-academy.lab=ch20 --mount type=volume,src=da20-data,dst=/data busybox:1.36.1 sh -c '
set -eu
printf "version=1\n" > /data/VERSION
printf "alpha\nbeta\ngamma\n" > /data/records.txt
sha256sum /data/VERSION /data/records.txt
ls -ln /data
' | tee evidence/write.txt
docker volume inspect da20-data > evidence/volume-after-write.json
The writer container is gone because of --rm; the
volume remains. That is the lifecycle separation the chapter is
teaching.
4. Replace the container, not the data
A new reader container mounts the same volume. It has a different container ID but observes the same persisted files.
docker run --rm --name da20-reader --label devops-academy.lab=ch20 --mount type=volume,src=da20-data,dst=/data,readonly busybox:1.36.1 sh -c '
cat /data/VERSION
cat /data/records.txt
sha256sum /data/VERSION /data/records.txt
ls -ln /data
' | tee evidence/read-after-replacement.txt
The read-only mount proves the second container needs no write permission for verification. Sequential sharing says nothing about whether the application would tolerate multiple concurrent writers.
5. Create a checksum-backed backup artifact
Because no writer is running, this file-level backup is consistent for the synthetic dataset. The helper mounts the source read-only and the host backup directory read-write.
docker run --rm --name da20-backup-helper --label devops-academy.lab=ch20 --mount type=volume,src=da20-data,dst=/source,readonly --mount type=bind,src="$(pwd)/da20-backup",dst=/backup busybox:1.36.1 sh -c '
set -eu
cd /source
tar -czf /backup/da20-data-v1.tgz .
sha256sum /backup/da20-data-v1.tgz > /backup/da20-data-v1.tgz.sha256
'
cat da20-backup/da20-data-v1.tgz.sha256
sha256sum -c da20-backup/da20-data-v1.tgz.sha256
If your shell/host uses different bind-path syntax, adapt only the source path and record the platform-specific substitution. The backup filename and checksum remain the evidence contract.
6. Restore into a new volume
Never overwrite the original first when testing recovery. Create a fresh target, extract the archive there, then compare logical content and file checksums.
docker volume create --driver local --label devops-academy.lab=ch20 --label devops-academy.purpose=restore-target da20-restore
docker run --rm --name da20-restore-helper --label devops-academy.lab=ch20 --mount type=volume,src=da20-restore,dst=/restore --mount type=bind,src="$(pwd)/da20-backup",dst=/backup,readonly busybox:1.36.1 sh -c '
set -eu
cd /restore
tar -xzf /backup/da20-data-v1.tgz
cat VERSION
cat records.txt
sha256sum VERSION records.txt
ls -ln .
' | tee evidence/restore.txt
7. Compare source and restored content independently
docker run \
--rm \
--mount type=volume,src=da20-data,dst=/data,readonly busybox:1.36.1 sh -c 'cd /data; sha256sum VERSION records.txt' | sort > evidence/source-files.sha256
docker run \
--rm \
--mount type=volume,src=da20-restore,dst=/data,readonly busybox:1.36.1 sh -c 'cd /data; sha256sum VERSION records.txt' | sort > evidence/restored-files.sha256
diff -u evidence/source-files.sha256 evidence/restored-files.sha256
An empty diff verifies byte equality for these files.
It does not prove a database would be transactionally consistent;
consistency must be defined by the application.
8. Prove no container dependency before deletion
docker ps -a --filter volume=da20-data --no-trunc
docker ps -a --filter volume=da20-restore --no-trunc
docker volume inspect da20-data da20-restore > evidence/volumes-final.json
If either query lists an unexpected container, stop and investigate ownership. Do not force deletion to make cleanup succeed.
9. Exact cleanup
docker volume rm da20-data da20-restore
docker volume ls --filter label=devops-academy.lab=ch20
# Keep ./da20-backup and ./evidence until you have reviewed the recovery evidence.
# No broad volume/system prune is part of this lab.
10. Challenge: choose the right layer
A replacement container starts successfully but reports “permission denied” on the restored volume. Which layer should you inspect first: registry, network, container image identity, or storage ownership? Capture the restored files' numeric UID/GID and the replacement process UID/GID before changing anything. The likely first mismatch is storage authorization, not networking.
Knowledge check
Why does the backup helper mount the source volume read-only?
The backup step should not mutate the data it is trying to preserve; read-only expresses that invariant.
Why restore into da20-restore instead of
overwriting da20-data?
A new target preserves the source as evidence and lets you test recovery without risking the original data.
Does an empty file checksum diff prove database consistency?
No. It proves byte equality for the archived files, not transaction/application consistency at the time the backup was captured.
Why query containers by volume before removal?
A volume can outlive one container and be consumed by another; dependency evidence prevents accidental deletion.
What state changed when the first writer container exited?
The container object disappeared, but the named volume and its data remained.
Official references and version notes
-
Docker Docs — Volumes
— volume lifecycle, mount behavior, backup/restore examples,
read-only mounts,
volume-nocopy, subpaths, and removal. - Docker CLI — docker volume — create, inspect, list, remove, prune, and update subcommands.
- Docker CLI — docker volume inspect — driver, labels, options, scope, creation timestamp, and mountpoint where the driver exposes one.
- Docker CLI — docker volume create — driver selection, driver options, labels, and cluster-volume options.
- Docker CLI — docker volume rm — exact volume removal and in-use protection.
- Compose Specification — top-level volumes — project-managed versus external volumes and driver/option declarations.
-
Docker CLI — docker compose down
— default retention,
--volumesdeletion semantics, and external-volume protection. - Docker Docs — Volume plugins — driver boundaries and why remote/plugin semantics must be learned from the selected driver.
- Docker Engine 29 release notes — current Engine baseline.
Docker
Engine 29.8.1 is current; Docker Compose 5.5.1, Buildx 0.37.1, and
BuildKit 0.33.0 are the current upstream baselines used for
compatibility discussion. The mandatory labs use the built-in
local volume driver and BusyBox, require no paid
service, and record the learner's actual installed versions rather
than assuming they match upstream.
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.