Rootless Podman Image Storage
185 MB of images in `~/.local/share/containers/storage`, on your home filesystem and counted against your quota. The same layer directories read `1000 1000` from outside and `0 0` under `podman unshare`.
Containers and Images Guide 9 of 47 Intermediate
- 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 3 - the UID mapping shown there is what makes the ownership in step 3 make sense.
- A few images pulled, so there is something to look at.
-
Two directories, not one
Podman keeps persistent data and runtime data in different places, and the distinction matters when something goes wrong:
- graphroot -
~/.local/share/containers/storage. Images, layers, volumes. Survives reboots. - runroot -
/run/user/1000/containers. Locks, network state, the running container's scratch. On tmpfs, so a reboot clears it.
185 MB of images here, and
duis reading your home filesystem. That is the first practical consequence: images count against your home directory's quota, and on a machine where/homeis a small separate partition you will fill it long before the root filesystem notices.podman system dfgives the engine's own accounting, which is the number to quote when deciding what to prune.bash Example session podman info --format 'graphroot={{.Store.GraphRoot}} runroot={{.Store.RunRoot}} driver={{.Store.GraphDriverName}}'graphroot=/home/sysadmin/.local/share/containers/storage runroot=/run/user/1000/containers driver=overlaydu -sh ~/.local/share/containers/storage185M /home/sysadmin/.local/share/containers/storagels ~/.local/share/containers/storagedb.sqldefaultNetworkBackendlibpodnetworksoverlayoverlay-containersoverlay-imagesoverlay-layerssecretsstorage.lockuserns.lockvolumespodman system dfTYPE TOTAL ACTIVE SIZE RECLAIMABLEImages 5 0 188.4MB 188.4MB (100%)Containers 0 0 0B 0B (0%)Local Volumes 0 0 0B 0B (0%)Expected resultA graphroot under your home, a runroot under
/run/user, and roughly 185 MB across twelve entries.Success conditionYou can say which of the two directories survives a reboot.
- graphroot -
-
What the layout means
The directory names are the storage driver:
overlay,overlay-images,overlay-layers,overlay-containers. Change driver and you get a different set - which is why switching drivers appears to lose all your images.overlay-images/contains one directory per image, named by image ID, plusimages.json- the index that maps names and tags onto those IDs. A tag is a line in that file, which is why tagging is instant and costs no disk.db.sqlis Podman's own state database. Since there is no daemon holding state in memory, it has to be on disk - andstorage.lockis how concurrentpodmancommands avoid corrupting it.findmntconfirms there is nothing special underneath: plainext4on the root logical volume. No dedicated filesystem, no thin pool, no device mapper.bash Example session ls ~/.local/share/containers/storage/overlay-images/00c30ddf0ef8074bbc7b7e5ea655bb6d359dc66694edd57d70fe95ce6ba531aa7bc5ba2f958a043e123135f456af857350673b64eaddcf811698239f3a53d6e6c6348fa86ba0fb2108c9334f5fe913ddc6d853313e655891f133a0127c30099fd529dd0c6e5597ac7e4a3e2dea65c3fcc6173f4cae713c409265c1dd9914a11be2ac70e7319a02c5a477f5825259bd118b94e8b02c279c67afa63adab6d8685bimages.jsonimages.lockpodman image inspect docker.io/library/alpine --format 'driver={{.GraphDriver.Name}} layers={{len .RootFS.Layers}}'driver=overlay layers=1findmnt -T ~/.local/share/containers/storage -o TARGET,SOURCE,FSTYPETARGET SOURCE FSTYPE/ /dev/mapper/ubuntu--vg-ubuntu--lv ext4Expected resultFive image directories plus an index, a single-layer alpine, and
ext4.Success conditionYou can find the on-disk directory for a given image ID.
-
The same files, two owners
This is the parallel to the file test in guide 3, and it is worth seeing on the store itself.
ls -lnon the layer directories reports1000 1000- you own them, which is what makes rootless possible at all.The same
lsunderpodman unsharereports0 0. Same directories, same bytes, and root owns them - because inside the user namespace your UID 1000 *is* 0.podman unshareis the practical tool that falls out of this. When a file in the store or a volume is owned by a UID your account cannot touch, running the command inside the namespace puts you back in the world where you own it. It is the correct answer to "permission denied on a file I created", and it is better thansudo, which would move you to a different store entirely.bash Example session ls -ln ~/.local/share/containers/storage/overlay | head -4total 76drwx------ 5 1000 1000 4096 Aug 22 11:08 03430695163ab64f23824b1643197bd4f0762c2956f4ab5ac8bc33b7e9ca082cdrwx------ 6 1000 1000 4096 Aug 22 11:30 0958e0fef2d6a31e1325b8bfecd99dead933363682d69850a7606599023751bcdrwx------ 5 1000 1000 4096 Aug 22 11:08 0994c120661f7fe9296a272f0d48fdc6ea6c20341d91af32bb86d3064317d69fpodman unshare ls -ln ~/.local/share/containers/storage/overlay | head -4total 76drwx------ 5 0 0 4096 Aug 22 11:08 03430695163ab64f23824b1643197bd4f0762c2956f4ab5ac8bc33b7e9ca082cdrwx------ 6 0 0 4096 Aug 22 11:30 0958e0fef2d6a31e1325b8bfecd99dead933363682d69850a7606599023751bcdrwx------ 5 0 0 4096 Aug 22 11:08 0994c120661f7fe9296a272f0d48fdc6ea6c20341d91af32bb86d3064317d69fstat -c 'owner_uid=%u %n' ~/.local/share/containers/storage/overlayowner_uid=1000 /home/sysadmin/.local/share/containers/storage/overlayExpected result
1000 1000from outside and0 0from inside, for the same directories.Success conditionYou have read one directory's ownership two different ways and can explain both.
-
Root's store is a different, empty machine
sudo podman inforeports/var/lib/containers/storage, and it holds 160 KB and no images at all - on a host with 185 MB of them.Root has never pulled anything. There is no sharing, no fallback and no promotion between the two stores.
Two practical consequences:
- Disk is counted twice. Pull the same image rootless and rootful and it occupies space in both trees. On a machine where several users run containers, each has a full copy of every image they use.
sudois not a fix. Reaching for it when a rootless command fails gets you a working Podman with none of your images, which usually looks like a new and more confusing problem.
If you genuinely need one shared image store, that is what an additional store configured read-only in
storage.confis for - and it is a deliberate setup, not a default.bash Example session sudo -n podman info --format 'graphroot={{.Store.GraphRoot}}'graphroot=/var/lib/containers/storagesudo -n du -sh /var/lib/containers/storage160K /var/lib/containers/storagesudo -n podman imagesREPOSITORY TAG IMAGE ID CREATED SIZEExpected result
/var/lib/containers/storage, 160 KB, and an empty image list.Success conditionYou can explain why the same image can occupy disk twice on one host.
Troubleshooting
/homefilled up and you did not expect containers to be the cause.Why: Rootless images live under your home directory.
Fix:
podman system dffor the total, thenpodman system prune -ato remove unused images. Checkpodman volume lsbefore adding--volumes.You want the store somewhere else - a bigger disk.
Why: The default follows XDG, not free space.
Fix:Set
graphrootin~/.config/containers/storage.conf, thenpodman system resetor move the tree by hand while nothing is running. Confirm withpodman info --format '{{.Store.GraphRoot}}'.Error: ... database is lockedor a stale lock after a crash.Why:
storage.lockor state in the tmpfs runroot survived an unclean exit.Fix:Ensure no
podmanprocess is running, thenpodman system renumber. A reboot clears the runroot entirely since it is tmpfs.All your images vanished after changing the storage driver.
Why: Each driver has its own
overlay-*style directory tree. Nothing was deleted; Podman is reading a different one.Fix:Put the driver back and the images reappear. Migrating between drivers means re-pulling, or
podman saveandpodman load.