How to Migrate Docker Image Storage to containerd on Linux in 2025
Why Docker 29 Changed the Default Image Store
Docker 29 introduced a significant architectural shift by adopting containerd as the default image store for new installations. This change moves away from the legacy image storage format to a more modern, standards-compliant approach. The containerd image store offers better performance, improved compatibility with Kubernetes, and native support for modern container runtimes.
If you've upgraded to Docker 29 or later, or you're running existing installations alongside new deployments, understanding how to migrate to the containerd image store is essential.
Understanding the Storage Difference
The legacy Docker image store used a custom storage driver architecture that worked well for years. However, containerd uses the OCI Image Format specification, which provides:
- Better interoperability with Kubernetes and other container platforms
- Native support for snapshotters (storage backends like overlayfs, nativeFS)
- Improved performance for image operations
- Future-proof architecture aligned with industry standards
When you upgrade Docker Engine, existing images remain in the legacy store. New images pulled after the migration use the containerd store.
Prerequisites
Before migrating, ensure you have:
- Docker Engine 29 or later installed
- Linux system (Ubuntu 20.04+, Debian 11+, CentOS 8+, or similar)
- At least 5GB free disk space for image storage
- Docker daemon running with superuser access
- Backup of critical container configurations
Step 1: Check Your Current Storage Configuration
First, verify which image store your Docker installation is currently using:
docker info | grep -A 10 "Storage Driver"
You'll see output similar to:
Storage Driver: overlay2
Storage Location: /var/lib/docker
Logging Driver: json-file
For containerd, look for:
Storage Driver: containerd
If you see overlay2 or aufs, you're still using the legacy image store.
Step 2: Edit Docker Daemon Configuration
Modify the Docker daemon configuration file to enable containerd as the image store. Edit /etc/docker/daemon.json:
sudo nano /etc/docker/daemon.json
Add or modify the features section to include containerd-snapshotter:
{
"features": {
"containerd-snapshotter": true
},
"storage-driver": "overlay2"
}
If the file doesn't exist, create it with the above content. For existing configurations, merge the new settings while preserving other options like insecure-registries, registry-mirrors, or custom storage-driver settings.
Step 3: Restart Docker Daemon
Apply the configuration changes by restarting Docker:
sudo systemctl restart docker
Verify the restart was successful:
sudo systemctl status docker
Step 4: Verify containerd Integration
Confirm that Docker is now using containerd:
docker info | grep -A 5 "Storage"
You should see output indicating containerd integration is active.
Step 5: Manage Image Migration
Your legacy images remain in the old storage location. You have two options:
Option A: Let Docker Handle It Gradually
New images pulled after enabling containerd-snapshotter are automatically stored in the containerd image store. Old images continue working but use legacy storage.
# Pull a new image - this goes to containerd store
docker pull ubuntu:latest
# Your old images still work
docker run myapp:v1.0
Option B: Explicitly Migrate Specific Images
To move important images to the new store immediately:
# Re-pull the image to populate containerd store
docker pull myregistry/myapp:v1.0
# Verify it's in containerd store
docker images
Step 6: Clean Up Legacy Storage (Optional)
Once you've verified all critical images work with the new store, clean up unused legacy images:
# Remove unused images
docker image prune -a
# Clean up docker system (careful - this removes dangling layers)
docker system prune
Check disk space before and after:
du -sh /var/lib/docker
Troubleshooting Common Issues
Issue: Docker daemon won't start after configuration change
Verify JSON syntax in /etc/docker/daemon.json:
jq . /etc/docker/daemon.json
If there's a syntax error, fix it and retry the restart.
Issue: Images not appearing in containerd store
Confirm containerd-snapshotter is enabled:
docker info | grep containerd-snapshotter
If not enabled, check daemon logs:
sudo journalctl -u docker -n 50
Issue: Performance degradation after migration
Ensure your storage backend (overlayfs) is properly configured:
ls -la /var/lib/docker/
If you see excessive files, consider using fuse-overlayfs on systems without native overlayfs support.
Performance Considerations
The containerd image store typically improves:
- Image pull speed by 10-15% for large images
- Container startup time by utilizing OCI Image Format optimizations
- Disk usage through better deduplication
Monitor your system after migration:
docker system df
This command shows space used by images, containers, and build cache.
Migration Comparison Table
| Aspect | Legacy Store | containerd Store | |--------|--------------|------------------| | Default in Docker 29+ | No | Yes | | OCI Compliance | Partial | Full | | Kubernetes Compatibility | Indirect | Native | | Performance | Standard | Optimized | | Snapshotter Support | Limited | Full | | Migration Required | No | No* | | Coexistence Support | Yes | Yes |
*New images automatically use containerd store
Next Steps
After successful migration:
- Update CI/CD pipelines to leverage containerd features
- Test your applications with the new image store
- Document the change in your infrastructure runbooks
- Plan removal of legacy storage when no longer needed
- Monitor
docker system dfregularly for disk usage patterns
The transition to containerd-based image storage positions your Docker infrastructure for better Kubernetes integration and future container platform improvements.
Recommended Tools
- DockerDevelop faster. Run anywhere.
- DigitalOceanCloud hosting built for developers — $200 free credit for new users