Podman Volumes and Bind Mounts
A named volume is a directory in your rootless store that Podman manages; a bind mount is a path you chose. Both survive `podman rm`, and the ownership of what lands in them is where the two differ.
Storage Guide 32 of 47 Beginner
- OSUbuntu 26.04 LTS (resolute)
- Podman5.7.0
- Runtimecrun 1.21
- Networknetavark 1.16.1
- TimeAbout 13 min
- Reviewed22 August 2026
Written against the versions above. Podman follows the distribution here rather than a vendor repository, so the version you get is the one Ubuntu shipped. The commands are stable across 5.x.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| PODMAN01 | 192.168.0.24 | Ubuntu 26.04 LTS | Primary Container Host | 2 Core | 4 GB | 50 GB |
Before you start
- guide 14 - a named volume lives inside the store described there.
-
A named volume
podman volume create appdata, then mount it with-v appdata:/data. Podman recognises the bare name as a volume rather than a path.Inside, the file is owned by
0 0. Outside,ls -lnon the mountpoint reports the same file owned by1000 1000- the identity mapping from guide 3, applied to storage.podman volume inspectgives the real path:/home/sysadmin/.local/share/containers/storage/volumes/appdata/_dataInside your own store, under your home directory. Which means a named volume counts against your home filesystem exactly as images do - the same practical consequence as guide 14, and easy to forget because a volume has no size in
podman volume ls.bash Example session podman volume create appdataappdatapodman run --rm -v appdata:/data docker.io/library/alpine sh -c 'echo "written by root" > /data/f; ls -ln /data'total 4-rw-r--r-- 1 0 0 16 Aug 22 12:10 fpodman volume inspect appdata --format 'mount={{.Mountpoint}}'mount=/home/sysadmin/.local/share/containers/storage/volumes/appdata/_datals -ln $(podman volume inspect appdata --format '{{.Mountpoint}}')total 4-rw-r--r-- 1 1000 1000 16 Aug 22 12:10 fExpected resultA created volume, a file owned by
0inside and1000outside, and a mountpoint under your home directory.Success conditionYou can find a named volume's files from the host.
-
A bind mount, written by container root
-v ~/src:/srcmounts a path you chose. Podman tells the two forms apart by the leading/or~- a name is a volume, a path is a bind mount, and a typo in a volume name silently creates a new empty volume rather than erroring.The container reads
host.txtfine and writesby-container-root.txt. From the host, both files are owned by1000 1000- by you.So container root writing to a bind mount produces files you own. That is the convenient case, and it is the one people build a mental model on. The next guide is what happens when the container is not root.
bash Example session rm -rf ~/src && mkdir -p ~/src && echo "from the host" > ~/src/host.txt && ls -ln ~/srctotal 4-rw-rw-r-- 1 1000 1000 14 Aug 22 12:10 host.txtpodman run --rm -v ~/src:/src docker.io/library/alpine sh -c 'cat /src/host.txt; echo hi > /src/by-container-root.txt; ls -ln /src'from the hosttotal 8-rw-r--r-- 1 0 0 3 Aug 22 12:10 by-container-root.txt-rw-rw-r-- 1 0 0 14 Aug 22 12:10 host.txtrm -rf ~/src && mkdir -p ~/src && echo "from the host" > ~/src/host.txt && ls -ln ~/srctotal 4-rw-rw-r-- 1 1000 1000 14 Aug 22 12:10 host.txtExpected resultThe host file read from inside, and a new file owned by you outside.
Success conditionA container wrote into a directory of yours and you still own the result.
-
Which to use
Named volumes for data the application owns and you never touch by hand - a database, a queue, uploaded files. Podman manages the location, it is easy to back up as a unit (guide 62), and nothing outside the container is coupled to a path.
Bind mounts for data *you* own and the container reads - source code during development, configuration, a directory you want to inspect with ordinary tools. The point of a bind mount is that the host path is meaningful to you.
Two things that catch people:
- Mounting over a non-empty directory hides what was there. A named volume gets seeded with the image's content on first use; a bind mount does not, so binding an empty host directory over
/etc/nginxgives you an empty/etc/nginx. podman rmdoes not remove volumes. They accumulate.podman volume lsandpodman volume pruneare worth a periodic look, andpodman rm -vremoves a container's anonymous volumes with it.
bash Example session podman volume rm appdataappdataExpected resultThe volume removed.
Success conditionYou can say which of the two a given piece of data belongs in.
- Mounting over a non-empty directory hides what was there. A named volume gets seeded with the image's content on first use; a bind mount does not, so binding an empty host directory over
Troubleshooting
A bind mount appears empty inside the container.
Why: The host path did not exist, so Podman created an empty directory rather than failing.
Fix:Check the path on the host.
:roat least makes an accidental empty mount obvious, because writes fail.A named volume is empty when you expected the image's files.
Why: Seeding from the image happens only when the volume is brand new and empty.
Fix:
podman volume rmand let it be recreated, or copy the content in withpodman cp.Disk is filling and
podman system dfblames volumes.Why: Removed containers left their volumes behind.
Fix:
podman volume lsthenpodman volume prune. Check the list first - prune removes anything no container references.SELinuxdenials on a bind mount on RHEL or Fedora.Why: The host directory is not labelled for container access. Ubuntu uses AppArmor and does not have this.
Fix:Add
:z(shared) or:Z(private) to the mount. Harmless on Ubuntu, so it is worth including if the unit may travel.