Skip to content

containerd: docker system df -v incorrectly attributes shared content blobs as unique image size #52476

@minghangli-uni

Description

@minghangli-uni

Description

docker system df -v reports incorrect SHARED SIZE and UNIQUE SIZE when using the containerd image store.

For images built FROM another image (e.g. node:22), large portions of shared image content (base image layers) are incorrectly attributed to UNIQUE SIZE, even though they are clearly shared across images.

This leads to significantly inflated UNIQUE SIZE values that do not reflect the actual layer delta introduced by the derived image.

Reproduce

docker pull node:22

# minimal Dockerfile
cat <<EOF > Dockerfile
FROM node:22
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY index.js index.js
CMD ["node", "index.js"]
EOF

docker build -t express_app:v0.0.1 .

docker system df -v

One can see something similar,

REPOSITORY    TAG       SIZE      SHARED SIZE   UNIQUE SIZE
express_app   v0.0.1    1.64GB    1.216GB       421MB
node          22        1.64GB    1.216GB       424MB

However, express_app only introduces ~10–15MB of new layers (verified via docker history), but UNIQUE SIZE is reported as ~421MB.

Expected behavior

docker system df -v should correctly attribute shared and unique image size based on actual layer and content reuse.

For images built FROM another image:

  • Layers and content blobs referenced by multiple images should be counted as SHARED SIZE
  • Only layers and content introduced by the derived image should be counted as UNIQUE SIZE

For the example above:

node:22        → base image
express_app    → node:22 + small application layer (~10–15MB)

The expected output should reflect:

express_app UNIQUE SIZE ≈ size of newly added layers (~10–15MB)
node:22 UNIQUE SIZE ≈ minimal residual (if any)

docker version

Client:
 Version:           29.1.3
 API version:       1.52
 Go version:        go1.24.4
 Git commit:        29.1.3-0ubuntu3~24.04.1
 Built:             Fri Mar  6 11:35:12 2026
 OS/Arch:           linux/amd64
 Context:           default

Server:
 Engine:
  Version:          29.1.3
  API version:      1.52 (minimum version 1.44)
  Go version:       go1.24.4
  Git commit:       29.1.3-0ubuntu3~24.04.1
  Built:            Fri Mar  6 11:35:12 2026
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          2.2.1
  GitCommit:        
 runc:
  Version:          1.3.4-0ubuntu1~24.04.1
  GitCommit:        
 docker-init:
  Version:          0.19.0
  GitCommit:

docker info

Client:
 Version:    29.1.3
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.30.1
    Path:     /home/mli/.docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  2.40.3+ds1-0ubuntu1~24.04.1
    Path:     /usr/libexec/docker/cli-plugins/docker-compose
  trust: Manage trust on Docker images (Docker Inc.)
    Version:  29.1.3
    Path:     /usr/libexec/docker/cli-plugins/docker-trust

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 7
 Server Version: 29.1.3
 Storage Driver: overlayfs
  driver-type: io.containerd.snapshotter.v1
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 CDI spec directories:
  /etc/cdi
  /var/run/cdi
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 
 runc version: 
 init version: 
 Security Options:
  seccomp
   Profile: builtin
  cgroupns
 Kernel Version: 6.6.87.2-microsoft-standard-WSL2
 Operating System: Ubuntu 24.04.4 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 32
 Total Memory: 31.23GiB
 Name: DESKTOP-8RCR6T0
 ID: 7bf42676-71e1-41b8-a261-8508f0e5706c
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Experimental: false
 Insecure Registries:
  ::1/128
  127.0.0.0/8
 Live Restore Enabled: false
 Firewall Backend: iptables

Additional Info

After my current fix, the expected output is

$ docker system df -v
Images space usage:

REPOSITORY    TAG       IMAGE ID       CREATED       SIZE      SHARED SIZE   UNIQUE SIZE   CONTAINERS
express_app   v0.0.1    69be9ef22b10   2 hours ago   1.64GB    1.624GB       13.15MB       0
node          22        9059d9d7db98   6 days ago    1.64GB    1.624GB       16.18MB       0

I have a working fix for this and can submit a PR if that would be helpful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/imagesImage Servicecontainerd-integrationIssues and PRs related to containerd integrationkind/bugBugs are bugs. The cause may or may not be known at triage time so debugging may be needed.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions