Read Docker Disk Usage Before You Reclaim Anything

docker system df tells you how much space Docker is using and which category is responsible. It only reports; it removes nothing. Allow about ten minutes for a first check, spread across images, containers, volumes and build cache.

This guide follows Docker CE CLI 5:29.8.1-1~ubuntu.24.04~noble, reporting Docker version 29.8.1 on this machine. Your totals and names will differ. The command talks to the Docker daemon, so you need a working Docker context and permission to reach it. Normal inspection does not need sudo.

1. Confirm the command and daemon

Check the client version and ask Docker for its option list. Both are ordinary, read-only commands:

$ docker --version
Docker version 29.8.1, build 4a63305
$ docker system df --help
Usage:  docker system df [OPTIONS]

Show docker disk usage

Now run the default report:

$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          32        28        14.79GB   36.76MB (0%)
Containers      48        48        223.3MB   0B (0%)
Local Volumes   17        5         12.22GB   11.93GB (97%)
Build Cache     132       0         6.266GB   6.218GB

2. Read the summary without jumping to cleanup

Start with the largest SIZE, then compare its ACTIVE and RECLAIMABLE figures. In the sample above, local volumes and build cache deserve attention, while containers show no reported reclaimable space. That still does not make an inactive-looking volume safe to remove: a volume can hold the only copy of application data, and a build cache can shorten later builds.

ACTIVE is not a backup or ownership decision, just Docker's usage classification, and its meaning depends on the object type. Keep the report as evidence, then inspect the detailed rows before changing anything.

Checkpoint: save a baseline if you are chasing a disk alert. Redirecting output creates a report but does not touch Docker:

$ docker system df > docker-system-df-before.txt
$ test -s docker-system-df-before.txt && echo 'baseline saved'
baseline saved

3. Find the objects behind the totals

Add --verbose, or its short form -v, for per-image, per-container, volume and build-cache detail:

$ docker system df --verbose
Images space usage:

REPOSITORY   TAG       IMAGE ID       CREATED      SIZE    SHARED SIZE   UNIQUE SIZE   CONTAINERS
...

Containers space usage:

CONTAINER ID   IMAGE   COMMAND   LOCAL VOLUMES   SIZE   CREATED   STATUS   NAMES
...

Local Volumes space usage:

VOLUME NAME   LINKS   SIZE
...

Build cache usage: 6.266GB
...

Your report will list your own objects. For images, SHARED SIZE is data shared with another image and UNIQUE SIZE is data attributed only to that one. The displayed image SIZE is the virtual total of those two, so do not add up every image row and call the result extra disk usage. Containers show their writable-layer size, not their full image size.

The detailed volume section earns its keep whenever a summary is dominated by local volumes. A volume with zero links can still be deliberate: kept for a stopped service or a later restore. Check a volume's owner, backup status and contents with the relevant application tooling before running any removal command.

4. Produce machine-readable summary output

Use the documented JSON format when another program needs stable fields rather than aligned columns:

$ docker system df --format json
{"Active":"28","Reclaimable":"36.76MB (0%)","Size":"14.79GB","TotalCount":"32","Type":"Images"}
{"Active":"48","Reclaimable":"0B (0%)","Size":"223.3MB","TotalCount":"48","Type":"Containers"}
{"Active":"5","Reclaimable":"11.93GB (97%)","Size":"12.22GB","TotalCount":"17","Type":"Local Volumes"}
{"Active":"0","Reclaimable":"6.218GB","Size":"6.266GB","TotalCount":"132","Type":"Build Cache"}

This is one JSON object per line, not one JSON array. Process it as newline-delimited JSON, and treat fields such as Size and Reclaimable as display strings with units, not raw byte counts you can sort directly. Docker may report a reclaimable percentage in parentheses for some categories and omit it for others.

For a quick human-readable filter, use a Go template. The shell's single quotes keep the braces and dollar signs intact:

$ docker system df --format '{{.Type}}: {{.Size}} ({{.Reclaimable}} reclaimable)'
Images: 14.79GB (36.76MB (0%) reclaimable)
Containers: 223.3MB (0B (0%) reclaimable)
Local Volumes: 12.22GB (11.93GB (97%) reclaimable)
Build Cache: 6.266GB (6.218GB reclaimable)

Your values will differ. If a script needs JSON, prefer --format json over parsing the aligned table.

5. Investigate access and context failures

If Docker says it cannot connect to the daemon, check the selected context and daemon reachability without changing anything:

$ docker context show
default
$ docker info > /dev/null && echo 'daemon reachable'
daemon reachable
$ docker system df

Your context name may differ. An unreachable daemon is a service or context problem, not evidence that disk usage is zero. A permission error for the Docker socket means your account lacks access under the local security policy: use an approved group or administrative procedure, or run the read-only command with sudo only when that is the established policy. Adding your account to the Docker group grants broad control over the host, so do not treat that as a casual workaround.

If you are checking a remote context, remember the report describes the daemon that context selects, not necessarily the filesystem of the shell where you typed the command. Confirm the context before recording or comparing totals.

6. Keep cleanup separate

docker system df has no cleanup mode. Do not reach for a reclaim command just because the report shows a big percentage. Image, container, volume and builder pruning each have different matching rules and can remove data or cached work, and volume deletion is particularly risky because application data may live there.

Before any later cleanup, record the baseline, identify exact object IDs or names, confirm a backup and check whether a service is using the data. Schedule anything service-affecting separately. If an approved cleanup produces an unexpected result, stop and compare a fresh docker system df --verbose report with the baseline; do not repeat a broad prune just to make the numbers look tidy. This guide itself changes no Docker state, so none of its own commands need an undo.

Done means