Docker and Kubernetes course menu
Docker Volumes Explained: Keep Data When Containers Are Removed
Persist data with Docker volumes: create and attach them, share them between containers, keep a database's data, back them up and restore them, and clean up safely.
On this page
A container's writable layer disappears with the container. A database that lost its data at every update would be useless, so Docker provides volumes: storage that lives outside the container.
The problem#
docker run --name c1 alpine:3.24 sh -c 'echo "important" > /data.txt'
docker rm c1 > /dev/null
docker run --rm alpine:3.24 cat /data.txtcat: can't open '/data.txt': No such file or directoryUse a volume#
-v name:/path attaches a named volume at that path in the container. Docker creates the volume if needed:
docker run --rm -v notes:/data alpine:3.24 sh -c 'echo "important" > /data/note.txt'
docker run --rm -v notes:/data alpine:3.24 cat /data/note.txtimportantThe first container is gone, but the data is still there.
Manage volumes#
docker volume ls --format '{{.Name}} {{.Driver}}'
docker volume inspect notes --format '{{.Mountpoint}}'notes local
/var/lib/docker/volumes/notes/_dataDocker stores volumes in its own area on the host. You rarely need to look inside it.
Share a volume#
Several containers can use one volume at the same time:
docker run -d --name writer -v shared:/data alpine:3.24 sh -c 'echo "from writer" > /data/msg; sleep 30' > /dev/null
sleep 1
docker run --rm -v shared:/data:ro alpine:3.24 cat /data/msg
docker rm -f writer > /dev/nullfrom writer:ro mounts it read-only.
A real database#
The official PostgreSQL image stores its data in /var/lib/postgresql/data. Attach a volume there:
docker run -d --name db -e POSTGRES_PASSWORD=devpass -v pgdata:/var/lib/postgresql/data postgres:17-alpine > /dev/null
until docker exec db pg_isready -q; do sleep 1; done
sleep 2
docker exec db psql -U postgres -qc "CREATE TABLE notes (body text); INSERT INTO notes VALUES ('Saved in a volume');"
docker rm -f db > /dev/null
docker run -d --name db -e POSTGRES_PASSWORD=devpass -v pgdata:/var/lib/postgresql/data postgres:17-alpine > /dev/null
until docker exec db pg_isready -q; do sleep 1; done
sleep 1
docker exec db psql -U postgres -tAc "SELECT body FROM notes;"
docker rm -f db > /dev/nullSaved in a volumeWe deleted the container and made a new one, and the data survived. This is how you upgrade a database container safely.
Back up a volume#
There is no special command. Run a short-lived container with the volume, and a folder for the archive:
mkdir backup
docker run --rm -v notes:/data:ro -v "$PWD/backup":/backup alpine:3.24 tar -czf /backup/notes.tar.gz -C /data .
ls backup
docker volume create restored > /dev/null
docker run --rm -v restored:/data -v "$PWD/backup":/backup alpine:3.24 tar -xzf /backup/notes.tar.gz -C /data
docker run --rm -v restored:/data alpine:3.24 cat /data/note.txtnotes.tar.gz
importantFor databases, use their own tool, such as pg_dump, because copying the files of a running database may not give a consistent backup.
Clean up#
docker volume rm notes restored
docker volume prune -af > /dev/null
docker volume ls -q | wc -lnotes
restored
0docker volume prune deletes volumes not used by a container. Read the list carefully on a real server.
Common mistakes#
Practice#
Practice exercise
Create a volume called counter. Run a container three times, each adding one line to /data/visits.txt, then print the number of lines.
Show solution
for i in 1 2 3; do
docker run --rm -v counter:/data alpine:3.24 sh -c 'echo visit >> /data/visits.txt'
done
docker run --rm -v counter:/data alpine:3.24 wc -l /data/visits.txt3 /data/visits.txtKey takeaway#
Next: Bind Mounts.
Finished this lesson?
Related lessons
Recommended Docker and Kubernetes resources
- Docker Deep Dive by Nigel Poulton
A practical guide to how Docker works, for readers who have finished the basics.
Some links are affiliate links. If you buy through them, Laviyx Learn may earn a commission at no extra cost to you. As an Amazon Associate, we earn from qualifying purchases.