Run docker info on any Linux machine and the answer is on the Docker Root Dir line. On most installs that path is /var/lib/docker, a directory the Docker daemon manages on its own.
Docker Desktop on Windows and Mac keeps the same data inside a virtual disk file, so there’s no plain folder to open and browse.
Docker Engine 29.0 switched fresh installations to the containerd image store by default, according to Docker’s own engine documentation. Hosts upgraded from an older release stay on the classic overlay2 driver unless someone reconfigures them. With the containerd image store, image content sits under /var/lib/containerd, and volumes and configuration stay in /var/lib/docker.
What Is the Docker Image Storage Location

The daemon keeps every layer, manifest and scrap of metadata it has pulled or built in one place on disk. Nothing else is supposed to touch it.
It isn’t a database, and it isn’t a registry. It’s a filesystem path the daemon owns.
Every Docker image comes from somewhere else first. Most get pulled from Docker Hub or a private registry, then unpacked layer by layer once they land locally.
It has nothing to do with the build context used during a docker build, and it isn’t the writable filesystem of a running container either. The remote registry the image came from is a different thing again.
The exact path and internal layout depend on your operating system and the active storage driver. Both come up below.
How Image Storage Differs from Container and Volume Storage
Image layers are read-only, and every container built from that image shares them.
A Docker container adds one thin writable layer on top. That layer disappears the moment the container is removed.
Volumes live in their own directory tree. Docker volumes are stored outside the image and container layers and get mounted in at runtime, so they aren’t baked into either one.
Deleting a container never deletes the image underneath it. People mix the two up all the time, and it’s a common reason docker system prune seems to behave unpredictably. Containers, images, volumes and build cache are pruned as separate targets, and volumes only go when you ask for them.
Where Docker Stores Images on Linux

/var/lib/docker is the default data-root on Linux installs using classic storage drivers, according to Docker’s own daemon documentation. Once the containerd image store is active, layers and content go to /var/lib/containerd instead, and changing data-root won’t move that directory.
To confirm the active path, run docker info and read the Docker Root Dir line.
That value comes from the same daemon process you bring up when you start the Docker daemon, whether through systemd or by hand.
Which subfolders you see inside /var/lib/docker depends on the storage driver in use.
- overlay2 holds the layer data when the classic overlay2 driver is active
- image stores image metadata and the image database for classic drivers
- containers keeps per-container configuration and logs
- volumes holds the data of named volumes
Rootless Docker’s Storage Path
Rootless installs skip /var/lib/docker completely.
The data directory defaults to ~/.local/share/docker, per Docker’s rootless mode documentation, because the daemon runs inside the calling user’s own namespaces. Daemon config sits under ~/.config/docker, and every pulled image ends up under ~/.local/share/docker.
Where Docker Stores Images on Windows

Docker Desktop on Windows runs on the WSL 2 backend by default these days, not Hyper-V.
The data disk is a virtual disk file under %LOCALAPPDATA%\Docker\wsl. Current releases keep it at %LOCALAPPDATA%\Docker\wsl\disk\docker\_data.vhdx, while older ones used %LOCALAPPDATA%\Docker\wsl\data\ext4.vhdx.
Either way it’s a virtual disk file, so File Explorer won’t show you a folder of image files.
Docker Engine is a Linux binary, and Windows needs somewhere Linux-shaped to run it. That’s why everything sits inside a lightweight virtual machine. The main disk holds the docker-desktop distribution and the engine itself (under \wsl\main\ext4.vhdx). The data disk holds every image, container and volume.
The .vhdx size you see in Windows reflects how far the disk has grown, not how much the images inside use right now. A VHDX file doesn’t shrink on its own when space is freed inside it. After a prune it can stay huge until the disk is compacted.
Where Docker Stores Images on Mac
macOS has nothing like /var/lib/docker.
Docker Desktop keeps every image, container and volume inside one virtual disk file at ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw.
The VM that runs Docker comes from whichever virtual machine manager you picked in Docker Desktop settings. That’s Docker VMM (beta), the Apple Virtualization framework, or the legacy HyperKit option. Docker.raw is a sparse file, so the size Finder reports can be larger than the space it really takes on disk.
You can’t open Finder and see individual image files. The disk grows on its own as images and containers pile up. On current releases, space freed inside it usually goes back to macOS quickly, though older setups on the qcow2 format could be slow about giving it back.
Running docker system prune frees space inside the virtual disk. If the file on the macOS side stays large afterward, check the disk usage settings in Docker Desktop or lower the disk image size limit.
How Storage Drivers Determine Where and How Images Sit on Disk

The storage driver translates Docker’s layered image format into actual filesystem operations.
overlay2 is built on the OverlayFS union filesystem and has been the Linux default for years. Docker’s documentation confirms it natively supports up to 128 lower OverlayFS layers, which is well beyond what the older overlay driver could handle.
Docker Engine 29.0 changed the default. Fresh installs now use the containerd image store instead of classic drivers like overlay2, according to Docker’s own documentation.
Upgraded systems stay on overlay2 unless reconfigured, so you’ll run into both setups in the wild.
| Storage Driver | Backing Filesystem | Layer Handling | Current Status |
|---|---|---|---|
| overlay2 | ext4 or xfs (with d\_type support) | Up to 128 lower layers, copy-on-write | Classic default, still widespread on upgraded hosts |
| containerd snapshotter | ext4 or xfs | Content-addressed snapshots | Default for fresh installs since Engine 29.0 |
| btrfs or zfs | btrfs or zfs volume | Layers stored as subvolumes or snapshots | Filesystem-specific, niche |
| vfs | any | Full copy per layer, no copy-on-write | Fallback and testing only |
| overlay (legacy) | ext4 or xfs | Lower layers shared through hard links | Removed in Engine 24.0 |
| aufs | ext4 or xfs | Union filesystem layers | Removed in Engine 24.0 |
| devicemapper | direct-lvm or loop-lvm | Block-level thin provisioning | Removed in Engine 25.0 |
The way overlay2 stacks read-only layers into one merged view is a good example of how containerization keeps images lighter than running full guest operating systems.
Rootless setups follow the same idea with different requirements. On a host with kernel 5.11 or newer, rootless Docker can use overlay2 directly. Where unprivileged overlay mounts aren’t supported, it uses fuse-overlayfs if that’s available, and falls back to vfs otherwise.
What a Stored Docker Image Actually Looks Like on Disk

A stored image isn’t one big file. It’s a manifest plus a stack of layer blobs, each identified by a content hash instead of a name.
The image manifest lists which layers belong to the image and in what order, following the structure defined by the OCI Image Specification.
Each layer sits on disk as a compressed blob named after the SHA256 digest of its own contents.
That content-addressable setup pays off in a few ways. Two images sharing a base layer reuse the exact same blob instead of duplicating it. A layer’s digest changes the moment its contents change, so caching stays reliable. And a corrupted or tampered layer is easy to spot, because the stored hash and the actual content stop matching.
BuildKit and the Dockerfile build cache lean on the same structure. When an instruction hasn’t changed, the layer it would produce already exists on disk under its old digest, so the build reuses it instead of starting over.
How Much Disk Space Docker Images Actually Use

Images rarely account for all the space Docker claims on a host.
Containers, local volumes and the build cache compete for the same disk, and each gets its own line in a disk usage report.
Docker Docs has an example docker system df report worth looking at. It lists 5 images (2 active) at 16.43 MB total, with 11.63 MB of that reclaimable, which is 70%. The 2 containers are both stopped and come to 212 B, all of it reclaimable. Of the 2 local volumes, 1 is active and none of the space is reclaimable.
That reclaimable share isn’t unusual. Unused base layers, superseded tags and dangling images stack up fast once a project has been through a few build cycles.
| Metric | What It Measures |
|---|---|
| Size | Full virtual size of the image, shared layers included |
| Shared size | Space the image has in common with at least one other image |
| Unique size | Space that disappears if that specific image is removed |
A high reclaimable percentage almost always points to old, untagged layers and not the images you’re still using.
Clearing them out means following the steps to remove Docker images you no longer need.
How to Move the Docker Image Storage Location
You tell the daemon to use a new data-root, then physically relocate the existing data so nothing gets orphaned.
Community tutorials, DigitalOcean’s among them, cover this same process for servers running low on root disk space. They use a daemon.json data-root setting and an rsync copy.
- Stop the Docker daemon completely (sudo systemctl stop docker, plus docker.socket on systemd hosts)
- Confirm no docker processes remain running
- Edit or create /etc/docker/daemon.json and add a data-root key pointing to the new path
- Copy the existing directory contents with rsync -aP /var/lib/docker/ /new/path/
- If the containerd image store is active, also copy /var/lib/containerd/ and set the root option in the containerd configuration (config.toml), because data-root does not move it
- Start the daemon again and confirm the new Docker Root Dir with docker info
- Once verified, remove the old directory to reclaim the original space
Every command in that sequence, from stopping the daemon to checking Docker Root Dir afterward, shows up in a typical Docker cheat sheet next to the other daemon lifecycle commands.
The upside of relocating is pretty clear. The root partition stops filling up with an ever-growing directory, and images can sit on faster storage like an SSD without moving the whole OS. Existing images and containers stay intact too, as long as you follow the steps in order.
The downsides are real, though. You need full daemon downtime during the copy, and a big /var/lib/docker makes the rsync step slow. Skip the stop step and you risk corrupting layers mid-copy.
Storing Images on an External or Network Drive
An external USB or Thunderbolt drive works like any other data-root target, as long as it’s mounted at the same path on every boot.
Network-attached storage is a different story. A single daemon pointed at a dedicated NFS mount can work in limited setups. Two daemons sharing one NFS directory produce errors that are difficult to troubleshoot, per Docker’s own daemon configuration documentation, and sharing one data-root across hosts is explicitly discouraged for that reason.
When Relocating Docker’s Storage Location Does Not Work

Not every host can point data-root somewhere new and carry on as before.
Switching storage drivers breaks existing data. Docker’s documentation says plainly that changing the driver makes existing containers and images inaccessible on the local system, since each driver keeps its own on-disk layout.
The recommended workaround is to save or push images elsewhere before the switch, either with docker save locally or a push to Docker Hub or a private registry.
Filesystem mismatches cause their own trouble. overlay2 on xfs requires d\_type=true, confirmed in Docker’s OverlayFS driver documentation. An xfs filesystem formatted without the ftype=1 option fails that check, and overlay2 won’t run correctly on it. devicemapper’s default loop-lvm mode used sparse files and was explicitly not recommended for production. The driver has since been removed in Engine 25.0.
Discourse’s installation script checks the active storage driver before proceeding and refuses to continue if it finds one that isn’t supported, since unsupported drivers have produced broken installs before. Its documentation describes a –skip-prereqs option for overriding the check.
An NFS-mounted data-root shared between two daemons throws errors that are hard to trace back to their cause.
Docker Desktop’s virtual disk can’t be redirected by editing a data-root path the way a native Linux daemon can, since the disk is a single opaque file and not a folder. Docker Desktop on Mac, Linux and Windows with the Hyper-V backend offers a Disk image location setting under Settings, Resources, Advanced. The WSL 2 backend doesn’t list that setting, so moving its disk means exporting or moving the WSL distribution instead.
FAQ on Where Are Docker Images Stored
Is the docker build cache stored in the same place as images?
Often, yes. With the default docker driver, the build cache is managed by the daemon and lives in the same data directory as pulled images. Builders created with other drivers, such as docker-container, keep their cache in their own separate storage.
docker system df tracks it on a separate line, since cache layers aren’t always tied to a tagged image.
Does deleting files directly from the storage directory work instead of using Docker’s own commands?
No. Manually removing files under /var/lib/docker corrupts the daemon’s internal metadata and breaks the image database.
Use docker image rm or docker system prune instead.
Do Docker images get removed automatically over time?
Not by default. Docker keeps every pulled or built image indefinitely unless a person or a scheduled job runs docker image prune.
Some CI runners add cleanup steps, but the daemon never deletes images on its own.
Does Podman store images in the same location as Docker?
No. Podman uses its own storage library. Root users get /var/lib/containers/storage by default, and rootless mode uses ~/.local/share/containers/storage.
That path stays separate from Docker’s data-root even when both run on the same host.
Can antivirus software interfere with the docker storage directory?
Yes. Real-time scanners that lock files during reads can slow copy-on-write operations inside overlay2 or the containerd snapshotter.
On Windows this often means excluding the WSL 2 data disk from active scanning to get reliable performance.
Does Docker store any image data in the cloud?
Not on its own. Docker Hub and private registries hold images remotely before a pull.
Once an image lands on a host, it sits entirely on that machine’s own disk or virtual disk, with no ongoing cloud dependency.
What Fills Up the Docker Image Storage Location First?
Build cache and dangling layers usually fill the disk long before the images you actually use, and neither clears itself automatically.
Docker’s build cache documentation lists a default garbage collection limit of 20GB for the docker driver in Docker Desktop. Most teams never touch it until a build fails on disk space. Builders created with other drivers use their own defaults, which can be set in buildkitd.toml.
The order you fix things in matters. Check the disk usage report before touching anything. Prune the build cache first, since it grows fastest. Relocate the storage directory only if pruning still leaves too little room.
Aggressive pruning frees space immediately, but the next build has to re-download or rebuild layers it had already cached, so that first run is noticeably slower.
Knowing how a container registry supplies those layers in the first place explains why local pruning never touches the remote copy.
- MySQL Cheat Sheet - September 30, 2026
- How to Remove Duplicate Lines in Notepad++ (Sorted or Unsorted) - September 29, 2026
- Should Your Engineering Team Still Own the Marketing Website? - September 29, 2026



