Session 8 · Volumes: keeping data safe#
The big idea#
Everything a container writes goes into its own writable layer, and that layer is deleted with the container. For a database, uploads or logs that is a disaster. A volume is a folder managed by Docker that lives outside any one container. Mount it into a container and the data survives restarts, removals and upgrades. A bind mount is the simpler cousin: it shows an ordinary folder from your computer inside the container.
Everyday example: a hotel room and a locker. Everything you leave loose in the room is cleared when you check out (the container is removed). Valuables kept in the hotel’s locker (a volume) are still there for your next stay, and any room can be given the locker key.
Losing data, then keeping it#
docker rm -f dm-v1 dm-v2 dm-b1 >/dev/null 2>&1
docker volume rm dm-data >/dev/null 2>&1
echo '--- data written in a container without a volume is lost with it'
docker run --name dm-v1 alpine sh -c 'echo "note 1" > /data.txt'
docker rm dm-v1 >/dev/null
docker run --rm alpine ls /data.txt 2>&1 | sed 's/^/new container: /'
echo '--- a named volume outlives the container'
docker volume create dm-data
docker run --rm -v dm-data:/data alpine sh -c 'echo "note 1" > /data/note.txt'
docker run --rm -v dm-data:/data alpine cat /data/note.txt
echo '--- two containers can share the same volume'
docker run --rm -v dm-data:/data alpine sh -c 'echo "note 2" >> /data/note.txt'
docker run --rm -v dm-data:/data alpine cat /data/note.txt
echo '--- list volumes'
docker volume ls --filter name=dm-data --format '{{.Driver}} {{.Name}}'
echo '--- a bind mount shows a host folder inside the container'
mkdir -p /tmp/dm-bind && echo "from the host" > /tmp/dm-bind/hello.txt
docker run --rm -v /tmp/dm-bind:/mnt alpine cat /mnt/hello.txt
echo '--- clean up'
docker volume rm dm-data
rm -rf /tmp/dm-bind
--- data written in a container without a volume is lost with it
new container: ls: /data.txt: No such file or directory
--- a named volume outlives the container
dm-data
note 1
--- two containers can share the same volume
note 1
note 2
--- list volumes
local dm-data
--- a bind mount shows a host folder inside the container
from the host
--- clean up
dm-data
Step by step:
Without a volume, the file written by the first container was gone for the next one. That is the problem.
docker volume create dm-datamade a named volume.-v dm-data:/datamounts it at/datainside a container. The note written there was read back by a different container.Sharing: a second container appended
note 2to the same file, and the next container saw both lines. One volume can be used by several containers (be careful with two writers at once).docker volume lslists it with thelocaldriver, meaning it lives on this machine.Bind mount:
-v /tmp/dm-bind:/mntshowed the host filehello.txtinside the container. Edit it on the host and the container sees the change straight away. This is perfect for development.
Volume or bind mount?#
Named volume |
Bind mount |
|
|---|---|---|
You name |
A volume ( |
A host path ( |
Managed by |
Docker |
You |
Best for |
Databases, app data in production |
Source code while developing, config files |
Portable between machines |
Yes (via Docker) |
No, depends on the host path |
The pattern for databases is exactly this: for MySQL or PostgreSQL, mount a volume at the data folder
(-v pgdata:/var/lib/postgresql/data). The container can then be upgraded or recreated and the data stays.
Common mistakes#
Relying on the container’s own disk for important data. Anything not on a volume is temporary.
Mixing the two syntaxes.
-v dm-data:/data(no slash at the start) is a named volume;-v /tmp/dm-bind:/mnt(a path) is a bind mount. A typo in the name silently creates a new, empty volume.Deleting a volume by accident.
docker volume rmanddocker volume prunedelete data for good.docker rm -vremoves anonymous volumes attached to a container.Permission errors on bind mounts. The container’s user must be allowed to write to the host folder.
Backing up never. A volume is not a backup. Copy it out regularly (for example by tar-ing it from a throwaway container).
Hands-on exercises#
Exercise 1. Create a volume dm-notes, write hello to a file in it from one container, and read it from another.
Solution
docker volume create dm-notes
docker run --rm -v dm-notes:/n alpine sh -c 'echo hello > /n/a.txt'
docker run --rm -v dm-notes:/n alpine cat /n/a.txt
docker volume rm dm-notes
The second command prints hello.
Exercise 2. Show that a container sees live changes to a bind-mounted file.
Solution
mkdir -p /tmp/dm-live && echo one > /tmp/dm-live/f.txt
docker run -d --name dm-live -v /tmp/dm-live:/mnt alpine sleep 30
docker exec dm-live cat /mnt/f.txt
echo two > /tmp/dm-live/f.txt
docker exec dm-live cat /mnt/f.txt
docker rm -f dm-live; rm -rf /tmp/dm-live
First one, then two, without restarting the container.
Exercise 3. Run PostgreSQL with a volume so its data survives deleting the container. Which folder do you mount?
Solution
docker run -d --name pg -e POSTGRES_PASSWORD=secret -v pgdata:/var/lib/postgresql/data postgres:17-alpine
/var/lib/postgresql/data is where PostgreSQL keeps its files. Remove the container, start a new one with the same -v pgdata:..., and your
databases are still there.
Practice#
Take the Session 8 quiz. The original volumes guide and the MySQL volume task are in the reference section.