| Tested on | Red Hat Enterprise Linux 10.2 (Coughlan) |
|---|---|
| Package | podman-5.8.2-5.el10_2.x86_64 |
| Applies to | Linux hosts with Podman where you need to inspect local image, container, and volume disk usage and remove unused objects safely |
| Privilege | Rootful examples on the lab host; rootless users prune their own graph root under $HOME/.local/share/containers |
| Scope | podman system df and -v, --format JSON and Go templates, reclaimable-size caveats, podman system prune default scope, --all, --volumes, --filter, --build, --external, per-object container/image/network/volume/pod prune, measuring reclaimed space versus host df, Podman 5.8.2 versus Podman 6 volume prune behavior, transient_store pointer, and a safe cleanup sequence. Does not cover emergency no space left on device recovery, storage corruption reset, or manual deletion inside the graph root. |
| Related guides | Remove containers with podman rm List containers with podman ps |
Before you delete anything, measure what Podman stores locally. podman system df summarizes images, containers, and volumes; podman system prune removes unused objects when you are ready. The two commands answer different questions — usage first, cleanup second.
This guide stays on routine maintenance. Emergency disk-full recovery and storage reset belong in dedicated troubleshooting articles, not broad rm -rf under the graph root.
Check Podman disk usage first
Start with the summary table:
podman system dfSample output on the lab host:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 23 0 649.7MB 649.7MB (100%)
Containers 0 0 0B 0B (0%)
Local Volumes 0 0 0B 0B (0%)Column meanings:
| Column | Meaning |
|---|---|
| TOTAL | Objects Podman knows about in this category |
| ACTIVE | Objects currently in use; meaning varies by category |
| SIZE | Logical storage attributed to the category |
| RECLAIMABLE | Space Podman estimates you could free with prune commands |
For images, active generally means an image has containers associated with it; for containers, active means running; for volumes, active means referenced/in use.
Run podman system df before any prune so you know which category grew. Re-running it after cleanup shows whether the change matched your expectation.
Use verbose disk usage with -v
The summary hides which image or volume actually consumes space. Add -v:
podman system df -vThe verbose report has three sections: Images (one row per local image reference), Containers (writable layer size and attached local volumes), and Local volumes (name, link count, and size).
Sample output (abbreviated from the lab host):
REPOSITORY TAG IMAGE ID CREATED SIZE SHARED SIZE UNIQUE SIZE CONTAINERS
localhost/prune-demo v1 3390dee6d56a ... 23.6MB 23.59MB 6.76kB 1
localhost/prune-demo v2 4f0c20a680a0 ... 23.6MB 23.59MB 9.33kB 0
CONTAINER ID IMAGE COMMAND LOCAL VOLUMES SIZE CREATED STATUS NAMES
f9a361b5dac4 localhost/prune-demo:v1 ... 0 ... ... Created prune-demo-stopped
VOLUME NAME LINKS SIZE
prune-vol-test 0 0BSHARED SIZE is layer data reused by other images. UNIQUE SIZE is data only this reference needs. CONTAINERS counts containers using the image.
Use -v to find the real consumer before you choose image prune versus volume prune.
Reclaimable image size is an estimate
RECLAIMABLE can overstate what a single prune will return. Images share layers — deleting one unused tag does not free a layer another image still references.
After creating two tags built from the same base and one stopped container, re-check the summary:
podman system dfSample output (images row on the lab host):
Images 25 1 649.7MB 649.7MB (100%)One image was ACTIVE (referenced by the stopped container), yet the summary reported 100% reclaimable on the image row. Treat RECLAIMABLE as guidance, not a promise that exactly that many bytes will return to the filesystem.
Get machine-readable disk usage
Scripts can parse structured output instead of the human table:
podman system df --format jsonSample output (trimmed):
[
{"Type":"Images","Total":23,"Active":0,"RawSize":649718690,"RawReclaimable":649718690,"Size":"649.7MB","Reclaimable":"649.7MB (100%)"},
{"Type":"Containers","Total":0,"Active":0,"RawSize":0,"RawReclaimable":0,"Size":"0B","Reclaimable":"0B (0%)"},
{"Type":"Local Volumes","Total":0,"Active":0,"RawSize":0,"RawReclaimable":0,"Size":"0B","Reclaimable":"0B (0%)"}
]A Go template line per category works for simple reporting:
podman system df --format '{{.Type}} {{.Size}} {{.Reclaimable}}'Sample output:
Images 649.7MB 649.7MB (100%)
Containers 0B 0B (0%)
Local Volumes 0B 0B (0%)This article stops at occasional checks — not a full monitoring pipeline.
What podman system prune removes by default
Default prune asks for confirmation. On Podman 5.8.2 the prompt lists stopped containers, unused networks, dangling images, and dangling build cache — unused pods are removed too even when the warning omits them:
podman system pruneSample prompt on Podman 5.8.2:
WARNING! This command removes:
- all stopped containers
- all networks not used by at least one container
- all dangling images
- all dangling build cache
Are you sure you want to continue? [y/N]Pass -f to skip the prompt in scripts:
podman system prune -fSample result after a stopped container and a dangling image existed:
Deleted Containers
f9a361b5dac4f0bb7e1929dae25ee493a998c8d6a5c562f8088173f39de7f74b
Deleted Images
4ecb1a33d817bc73db7d9ae33eca7a0c5c4e1ba3eeff4569aa62a6a8e50c71be
Deleted Networks
podman-default-kube-network
Total reclaimed space: 156MBTagged images such as localhost/prune-demo:v1 and named volumes were left intact. Volumes are not in the default scope — that protects persistent data. Unused pods are included in default system prune even when the confirmation prompt does not list them.
Remove all unused images with --all
--all extends image cleanup to every image without an associated container, not only dangling <none> layers:
podman system prune --allSample warning:
WARNING! This command removes:
- all stopped containers
- all networks not used by at least one container
- all images without at least one container associated with them
- all build cache
Are you sure you want to continue? [y/N]On the lab host podman system prune --all -f removed thirteen image IDs including both prune-demo tags and reported Total reclaimed space: 767.7MB. Volumes were still present afterward.
--all does not imply volume deletion. Add --volumes only when you intend to prune unused volumes too.
Prune volumes with system prune
Named data needs an explicit flag:
podman system prune --volumesSample warning:
WARNING! This command removes:
- all stopped containers
- all networks not used by at least one container
- all volumes not used by at least one container
- all dangling images
- all dangling build cache
Are you sure you want to continue? [y/N]Combine both aggressive image and volume cleanup only after review:
podman system prune --all --volumes -fUnused means not referenced by any container right now — not safe to delete. A named volume holding database files can show LINKS 0 in podman system df -v while still being data you need. List volumes and back up before --volumes:
podman volume lsUse filters on system prune
Limit cleanup by age:
podman system prune --filter until=24h -fLabel filters work when your objects carry metadata:
podman system prune --filter label=temporary=true -fFilters apply to the prune operation as a whole; they do not behave identically for every resource type. Podman 5.8.2 does not offer --dry-run on system prune — test with a narrow per-object prune or a disposable lab host first.
Clean up stale build containers with --build
Interrupted builds can leave build containers behind:
podman system prune --build -fUpstream warns that --build can interfere with active builds. Run it only when no build is in progress — not on every scheduled cleanup.
podman system prune --external
--external is a different mode, not a stronger system prune:
podman system prune --external -fIt removes storage data under the graph root that current Podman metadata does not reference — for example after an unclean shutdown or leftover writable layers when transient_store is enabled. On a healthy host the command may print nothing and exit successfully.
It cannot combine with normal prune options:
podman system prune --external --allSample error:
Error: system prune --external cannot be combined with other optionsDo not pass --all, --filter, or --volumes with --external.
--external and transient_store
When transient_store = true in storage.conf, container metadata is intentionally temporary and writable layers can survive a reboot. Upstream documentation recommends podman system prune --external during boot for that configuration. See Podman storage location for graph-root layout — do not enable transient_store just to exercise this flag on a normal server.
Per-object prune commands
Narrow cleanup is easier to reason about than a broad system prune:
| Resource | Command |
|---|---|
| Stopped containers | podman container prune |
| Images | podman image prune |
| Networks | podman network prune |
| Volumes | podman volume prune |
| Stopped pods | podman pod prune |
| Combined default set | podman system prune |
If only old images are the problem, podman image prune is safer than system prune --all until you have checked podman system df -v.
podman image prune
Default image prune removes dangling images only:
podman image pruneSample warning:
WARNING! This command removes all dangling images.Add --all to drop every image not used by a container:
podman image prune --allSample warning:
WARNING! This command removes all images without at least one container associated with them.Tag, inspect, and history workflows live in Manage images with podman images.
podman container prune
Remove all non-running containers:
podman container pruneSample warning:
WARNING! This will remove all non running containers.Confirm with podman ps -a first — stopped containers you plan to restart are still candidates. Filters such as until= and labels are supported on container prune.
podman network prune
Delete custom networks with no attached containers:
podman network prune -fSample output:
prune-unused-netBuilt-in networks such as podman are not removed like an unused custom bridge. Network design details belong in the networking articles.
Volume prune: Podman 5.8.2 versus Podman 6
Version behavior diverges — copy commands from the docs that match your installed Podman.
Podman 5.8.2 (this lab)
podman volume prune removes every volume not used by at least one container, including named volumes:
podman volume pruneSample prompt listing names before confirm:
WARNING! This will remove all volumes not used by at least one container. The following volumes will be removed:
prune-vol-test
6ac7c48e21bfa76c1df2e14339bea4031423d1cc4486ee2d1918e72a1882ff46
Are you sure you want to continue? [y/N]After -f, both the named volume and the anonymous hash-named volume were deleted. There is no --all or --dry-run on volume prune in 5.8.2.
Podman 6 and later
Default podman volume prune removes unused anonymous volumes only. Named unused volumes require podman volume prune --all. Newer releases may add --dry-run to preview deletions. Verify with podman volume prune --help on the host you administer — do not assume 6.x behavior on a 5.x machine.
Volume create, mount, and backup patterns are covered in Podman volumes.
Measure reclaimed space
Compare Podman logical totals with filesystem free space before and after cleanup.
Check the graph root filesystem:
df -h /var/lib/containers/storageSample output on the lab host:
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/rhel-root 25G 25G 717M 98% /Record Podman usage:
podman system dfRun your chosen prune, then repeat both commands. Logical Total reclaimed space from prune and df free-space delta can differ because of shared layers, filesystem allocation, open deleted files, and unrelated host activity. Small prunes may show 0B reclaimed in Podman while the graph root is still nearly full from other data.
Do not manually delete overlay directories
Never free space with:
rm -rf /var/lib/containers/storage/overlay/*Rootless stores use paths under $HOME/.local/share/containers — the same rule applies. Hand-deleting layer directories desynchronizes metadata from on-disk storage.
Use podman rm, podman rmi, podman volume rm, and prune subcommands. If metadata is already broken, follow Podman storage corruption and reset. If the filesystem is completely full, see Fix Podman no space left on device.
Recommended safe cleanup sequence
Routine maintenance on Podman 5.8.2:
- Run
podman system df -vand identify which type — images, containers, or volumes — grew. - Prefer per-object prune (
image prune,container prune,volume prune) when only one category is the problem. - Re-run
podman system dfand confirm the summary changed as expected. - Use
podman system prunewhen you want the default bundle (stopped containers, unused pods, unused networks, dangling images, dangling build cache). - Add
--allonly when tagged unused images should go. - Add
--volumesonly afterpodman volume lsand backups — unused named data is still data. - Use
--buildonly when no build is running. - Reserve
--externalfor orphan storage after transient store or unclean shutdown — never combined with--all.
That sequence keeps inspection before deletion and matches how Podman 5.8.2 actually scopes each flag.
Cleanup
If you created lab fixtures during practice, remove leftover objects with targeted commands rather than editing storage by hand:
podman rm -f prune-demo-stopped 2>/dev/null
podman volume rm prune-vol-test 2>/dev/null
podman rmi localhost/prune-demo:v1 localhost/prune-demo:v2 2>/dev/nullSummary
podman system df shows where Podman disk usage lives; podman system prune removes unused objects when you choose the right flags. Always measure with df and -v before pruning — RECLAIMABLE can overstate frees when images share layers.
Default system prune clears stopped containers, unused pods, unused networks, dangling images, and dangling build cache but keeps tagged unused images and all volumes. --all adds unused tagged images; --volumes is separate and dangerous for named data. On Podman 5.8.2, volume prune already targets unused named volumes — Podman 6 narrows the default unless you pass --all. --external cleans orphan storage and cannot mix with normal prune options.
Never delete overlay trees manually. For corruption or a full disk, use the dedicated troubleshooting guides instead of broad rm -rf under the graph root.
References
- podman-system-df(1) — disk usage summary and
-v - podman-system-prune(1) — default scope,
--all,--volumes,--build, and--external - podman-volume-prune(1) — current default: anonymous volumes only; use
--allfor unused named volumes - podman-volume-prune(1) — Podman 5.8.2 — 5.x default: all unused volumes unless filtered
- containers-storage.conf(5) —
transient_storeand graph root - Podman storage location — graph root and
transient_storecontext

