Skip to content

Docker Storage

  • Docker uses a layered storage model based on a Union Filesystem (UnionFS). Image layers are read-only. When a container runs, Docker adds a thin read-write layer on top.
  • All runtime writes go into the container’s writable layer - this data is ephemeral and deleted with the container.
  • For persistent data, use volumes or bind mounts.

The storage driver manages how image layers and the container’s writable layer are stored and stacked on the host. Docker selects a driver automatically based on the OS.

DriverOSNotes
overlay2LinuxDefault and recommended. Uses overlayfs kernel feature. Best performance.
fuse-overlayfsLinux (rootless)Rootless Docker fallback when overlayfs needs root.
btrfsLinux (btrfs fs)Native driver for Btrfs filesystems.
zfsLinux (ZFS)Native driver for ZFS filesystems.
devicemapperLegacy LinuxDeprecated. Thin-pool instability at scale, no upstream maintenance. Do not use.
aufsLegacy UbuntuDeprecated. Replaced by overlay2.
vfsAll (testing)No copy-on-write. Every layer is a full copy. Extremely slow. Testing only.
Terminal window
# Check which storage driver Docker is using
docker info | grep "Storage Driver"
  • overlay2 uses the Linux overlayfs to present a merged view of multiple read-only layers + one read-write layer.
  • Copy-on-Write (CoW): When a container modifies a file from an image layer, the file is first copied to the writable layer, then modified. The original image layer is untouched.
  • Multiple containers based on the same image share the read-only layers - only their thin writable layers are unique.
/var/lib/docker/overlay2/
├── <layer-id>/ # Each image layer
│ ├── diff/ # Files in this layer
│ ├── link # Short name for this layer
│ └── lower # Pointer to parent layer
└── <container-layer>/ # Container's writable layer
└── merged/ # The unified filesystem view (what the container sees)

Everything Docker manages on the host lives under /var/lib/docker/ (or C:\ProgramData\docker\ on Windows).

/var/lib/docker/
├── image/ # Image layer metadata and digests
├── overlay2/ # Actual layer filesystems (storage driver specific)
├── containers/ # Per-container metadata, logs, and writable layers
├── volumes/ # Named volume data
└── networks/ # Network configuration
Terminal window
# Get the full storage path for a specific container
docker inspect <container-id> | grep -A5 GraphDriver
# See disk usage by Docker components
docker system df
docker system df -v # Verbose - shows per-image and per-container sizes
# Remove unused images, stopped containers, networks, and build cache
docker system prune
docker system prune -a # Also removes all unused images (not just dangling)
docker system prune -a --volumes # Nuclear option — also removes all unused volumes (DATA LOSS risk)

[!note] On Docker Desktop (macOS/Windows), Docker runs inside a Linux VM. The /var/lib/docker path is inside that VM’s filesystem, not your host filesystem. Volume data similarly lives inside the VM unless using bind mounts to your host’s directories.

Storage drivers manage the container’s own filesystem. For application data that needs to survive container restarts or be shared, see Docker Mounting.

Storage Driver LayerVolumesBind Mounts
Managed byDockerDockerHost OS
Survives container removalNoYesYes
PerformanceCoW overheadNativeNative
PortabilityN/AHighLow (host path)