containerd image store with Docker Engine
The containerd image store is the default storage backend for Docker Engine 29.0 and later on fresh installations. If you upgraded from an earlier version, your daemon continues using the legacy graph drivers (overlay2) until you enable the containerd image store.
containerd, the industry-standard container runtime, uses snapshotters instead of classic storage drivers for storing image and container data.
NoteThe containerd image store is not available when using user namespace remapping (
userns-remap). See moby#47377 for details.
Why use the containerd image store
The containerd image store uses snapshotters to manage how image layers are stored and accessed on the filesystem. This differs from the classic graph drivers like overlay2.
The containerd image store enables:
- Building and storing multi-platform images locally. With classic storage drivers, you need external builders for multi-platform images.
- Working with images that include attestations (provenance, SBOM). These use image indices that the classic store doesn't support.
- Running Wasm containers. The containerd image store supports WebAssembly workloads.
- Using advanced snapshotters. containerd supports pluggable snapshotters that provide features like lazy-pulling of images (stargz) or peer-to-peer image distribution (nydus, dragonfly).
For most users, switching to the containerd image store is transparent. The storage backend changes, but your workflows remain the same.
Disk space usage
The containerd image store uses more disk space than the legacy storage drivers for the same images. This is because containerd stores images in both compressed and uncompressed formats, while the legacy drivers stored only the uncompressed layers.
When you pull an image, containerd keeps the compressed layers (as received from the registry) and also extracts them to disk. This dual storage means each layer occupies more space. The compressed format enables faster pulls and pushes, but requires additional disk capacity.
Importantcontainerd uses a separate storage path from the Docker data directory. If you previously configured a custom data directory for Docker (for example, to use a different partition), containerd's storage is not automatically moved to that location. You need to configure containerd's data directory separately to avoid filling your root partition.
To configure containerd's data directory, see Configure the data directory location.
If disk space is constrained, consider the following:
- Regularly prune unused images with
docker image prune - Use
docker system dfto monitor disk usage - Configure the data directory to use a partition with adequate space
Enable containerd image store on Docker Engine
If you're upgrading from an earlier Docker Engine version, you need to manually enable the containerd image store.
ImportantSwitching storage backends temporarily hides images and containers created with the other backend. Your data remains on disk. To access the old images again, switch back to your previous storage configuration.
Add the following configuration to your /etc/docker/daemon.json file:
{
"features": {
"containerd-snapshotter": true
}
}Save the file and restart the daemon:
$ sudo systemctl restart docker
After restarting the daemon, verify you're using the containerd image store:
$ docker info -f '{{ .DriverStatus }}'
[[driver-type io.containerd.snapshotter.v1]]
Docker Engine uses the overlayfs containerd snapshotter by default.
NoteWhen you enable the containerd image store, existing images and containers from the overlay2 driver remain on disk but become hidden. They reappear if you switch back to overlay2. To use your existing images with the containerd image store, push them to a registry first, or use
docker saveto export them.
Lazy pulling
With lazy pulling, containers can start before their images are fully downloaded. Remote snapshotters fetch layer data from the registry as containers need it.
Docker Engine enables lazy pulling by default when configured to use the nydus, overlaybd, soci, or stargz snapshotter.
With other snapshotters, including the default overlayfs, Docker downloads all layer content before the container starts unless you explicitly enable lazy pulling.
During a lazy pull, Docker skips downloading a layer if the snapshotter can mount it remotely or already has its snapshot. Docker downloads all other layers. For example, the stargz snapshotter can mount eStargz layers remotely, but plain gzip layers must be downloaded unless their snapshots already exist.
Saving and pushing images
Lazily pulled images can run even if some layer content is missing from the containerd content store. However, missing content affects saving and pushing:
docker savecan fail or produce an incomplete archive without reporting an error.docker pushcannot upload missing layers, but can reuse them if the target registry supports mounting them from the source repository.
Running the image is not guaranteed to fill in the missing content in the containerd content store. For example, the stargz snapshotter keeps the data it fetches in its own cache. See moby#53878 for details.
Configuration
To disable lazy-pulling, set the lazy-pull feature to false in /etc/docker/daemon.json:
{
"features": {
"containerd-snapshotter": true,
"lazy-pull": false
}
}Reload the daemon configuration to apply the setting to subsequent pulls. For images you already pulled lazily, pull them again to download the missing content.
To enable lazy pulling for a snapshotter outside the default list, set lazy-pull to true instead.
Experimental automatic migration
Docker Engine includes an experimental feature that can automatically switch to the containerd image store under certain conditions. This feature is experimental. It's provided for those who want to test it, but starting fresh is the recommended approach.
CautionThe automatic migration feature is experimental and may not work reliably in all scenarios. Create backups before attempting to use it.
To enable automatic migration, add the containerd-migration feature to your
/etc/docker/daemon.json:
{
"features": {
"containerd-migration": true
}
}You can also set the DOCKER_MIGRATE_SNAPSHOTTER_THRESHOLD environment
variable to make the daemon switch automatically if you have no containers and
the total size of all image layers is at or below the threshold. The value is a
human-readable size (for example, 200M or 1G). For systemd:
$ sudo systemctl edit docker.service
Add:
[Service]
Environment="DOCKER_MIGRATE_SNAPSHOTTER_THRESHOLD=200M"If you have no running or stopped containers and the total size of all image layers is 200M or less, the daemon switches to the containerd image store on restart. Your overlay2 data remains on disk but becomes hidden.
Additional resources
To learn more about the containerd image store and its capabilities in Docker Desktop, see containerd image store on Docker Desktop.