Docker Engine v29: A Foundation Release That Shapes the Future
Docker Engine v29 isn't your typical feature-rich release. There are no flashy new CLI commands or eye-catching dashboard changes. Instead, this release lays critical groundwork that will define Docker's architecture for years to come. If you're running Docker Engine directly on Linux, understanding these changes is essential—not because you'll see dramatic differences today, but because they set the stage for everything coming next.
In this article, we'll break down every major architectural change in Docker Engine v29: the API version bump, the containerd image store becoming the default, the Go modules migration, experimental nftables support, and the critical security fix in Docker Desktop 4.44.3 (CVE-2025-9074). We'll cover what these changes mean, why they matter, and exactly what you need to do.
Background: Why This Release Matters
Docker has been evolving its architecture for years. The company originally created containerd as a core component of Docker, then donated it to the Cloud Native Computing Foundation (CNCF). Since then, containerd has become the industry-standard container runtime—powering not just Docker but Kubernetes and countless other platforms.
Docker Engine v29 represents the next logical step in this evolution. It's a "foundation release" that cleans up technical debt, aligns with ecosystem standards, and prepares the platform for future innovations. According to Docker's official announcement, these changes "improve maintainability, developer experience, and interoperability across the container ecosystem."
If you're using Docker Desktop, you're largely protected from these changes—updates are bundled automatically in future Desktop releases. But Linux users running Docker Engine directly need to understand what's happening under the hood.
1. Minimum API Version Update
What Changed
Docker Engine v29 increases the minimum supported API version from 1.43 to 1.44 (which corresponds to Moby v25). This means older Docker clients will no longer work with newer Docker Engine versions.
If you're using an outdated Docker client, you'll see this error:
Error response from daemon: client version 1.43 is too old.
Minimum supported API version is 1.44, please upgrade your client to a newer version
Why This Matters
Docker versions older than v25 are now end-of-life. The API version bump ensures that all clients connecting to Docker Engine v29 meet modern standards, which is crucial for security and compatibility.
How to Handle It
Option 1: Upgrade your Docker client (Recommended)
Simply update your Docker CLI to match your Docker Engine version:
# Check your current versions
docker version
# Update Docker Engine (example for Ubuntu/Debian)
sudo apt update
sudo apt upgrade docker.io
Option 2: Override the minimum API version (Not recommended for production)
If you absolutely must use an older client, you can override the minimum API version—though Docker explicitly warns against this for production environments.
Using environment variable:
DOCKER_MIN_API_VERSION=1.24 dockerd
Using daemon.json:
{
"min-api-version": "1.24"
}
Save this to /etc/docker/daemon.json and restart Docker:
sudo systemctl restart docker
⚠️ Warning: Using an older API version may expose you to security vulnerabilities and compatibility issues. Only use this as a temporary mitigation.
2. Containerd Image Store Becomes the Default
The Big Shift
Starting with Docker Engine v29, the containerd image store is now the default for new installations. This is a fundamental architectural change.
Previously, Docker used "graph drivers" (like overlay2, devicemapper, aufs) to manage image layers and container storage. While Docker adopted containerd for container execution years ago, it continued using graph drivers for storage.
Now, both execution and storage use containerd.
What This Means in Practice
For new installations, Docker will use containerd's image store by default. You might notice:
- Different behavior in
docker imagesanddocker build - Changes in how layer caching works
- Some container operations may behave slightly differently
Opting Out (If Needed)
If you're setting up a new Docker Engine v29 host and encounter issues, you can still disable the containerd image store. Add this to your daemon configuration:
{
"features": {
"containerd-image-store": "disable"
}
}
Then restart Docker:
sudo systemctl restart docker
Why This Change Matters
Simplified Architecture: Both execution and storage now use containerd, reducing internal complexity and maintenance burden.
-
Unlocks New Features: This enables future innovations like:
- Snapshotter innovations
- Lazy pulling of image content (like BuildKit's content-aware builds)
- Remote content stores
- Peer-to-peer image distribution
Ecosystem Alignment: Docker Engine now matches how Kubernetes and other containerd-based platforms work, improving interoperability.
Future-Proofing: The graph driver backend will eventually be removed entirely.
Migration Path for Existing Users
Here's the important part: existing Docker installations are NOT forced to migrate. You can continue using graph drivers. However, you can opt-in to try the containerd image store:
# Enable containerd image store (opt-in for existing installations)
docker features enable containerd-image-store
Docker is working on a migration guide to help teams transition their existing content to the containerd image store. The graph driver backend will be removed in a future release, so planning your migration is wise.
3. Moby Migrates to Go Modules
What Changed
The Moby project (the open-source codebase behind Docker Engine) has migrated from a legacy vendoring system to Go modules. This affects developers who consume Docker's Go APIs directly.
Important: Module Path Change
If you're importing Docker packages in your Go projects, you need to update your imports:
// OLD (no longer receives updates)
import "github.com/docker/docker/client"
// NEW (must use this going forward)
import "github.com/moby/moby/client"
Why This Matters
Go modules have been the Go community standard since 2019. The Moby project was one of the last major projects holding onto legacy vendoring. This change:
- Eliminates "constant maintenance churn" to work around tooling assumptions
- Provides clearer workflows for contributors
- Improves compatibility with modern Go tools
- Makes the Moby codebase easier to consume and integrate with
What This Means for You
If you're just using Docker (not programming against its Go APIs): This change is invisible to you. You won't see any UI or command changes.
If you're a Go developer consuming Docker's client or API packages: You must update your import paths. The old github.com/docker/docker path will no longer receive updates.
4. Experimental Support for nftables
What Changed
Docker Engine v29 introduces experimental support for nftables as an alternative to iptables for managing firewall rules on Linux.
Why This Matters
Currently, Docker creates firewall rules using iptables and ip6tables. On most modern Linux systems, these commands are actually symlinked to iptables-nft and ip6tables-nft, meaning Docker's rules get translated to nftables behind the scenes anyway.
However:
- Linux distributions are beginning to deprecate iptables support
- The translation layer adds overhead and complexity
- nftables offers more modern features and better performance
How to Enable nftables Support
Start Docker with the --firewall-backend=nftables flag:
dockerd --firewall-backend=nftables
Or add it to your daemon configuration:
{
"firewall-backend": "nftables"
}
Important Considerations
DOCKER-USER Chain Migration: If you use the
DOCKER-USERiptables chain for custom rules, you'll need to migrate it to nftables. See the official documentation for migration steps.Firewalld Integration: On hosts using firewalld, Docker will still set up firewalld zones and policies, but will create nftables rules directly.
Swarm Not Supported: At present, you cannot enable nftables support on a node with Docker Swarm enabled. Swarm support is planned for a future release.
Experimental: This feature is marked experimental. Don't deploy it in production without thorough testing.
IP Forwarding: After enabling nftables and rebooting, you may need to re-enable IP forwarding on the host:
# Check current setting
cat /proc/sys/net/ipv4/ip_forward
# Enable if needed (make persistent in /etc/sysctl.conf)
echo 1 > /proc/sys/net/ipv4/ip_forward
What's Coming
In a future release, nftables will become the default firewall backend, and iptables support will be deprecated. Now is the time to test and provide feedback.
5. Critical Security: CVE-2025-9074 and Docker Desktop 4.44.3
The Vulnerability
CVE-2025-9074 is a critical container escape vulnerability affecting Docker Desktop on Windows and macOS, with a CVSS score of 9.3 (out of 10).
Discovered by: Felix Boulet and Philippe Dugre (mid-2025)
What Was Wrong
Docker Desktop was exposing an unauthenticated Docker Engine API socket on the private Docker network at http://192.168.65.7:2375. This API, which provides powerful container management functions, was accessible to workloads running inside containers without any authentication.
Impact
Windows (Critical):
- Complete host takeover with administrator privileges possible
- Attackers can bind the host's filesystem (e.g., C:) into a new container
- Execute arbitrary code on the host
macOS (High):
- Docker manipulation and backdooring is possible
- Additional permission prompts limit (but don't eliminate) the risk
Linux (Not vulnerable by default):
- Docker Desktop on Linux uses a Unix named pipe for the Docker Engine API
- The TCP socket vulnerability doesn't exist
Exploitation
The attack is alarmingly simple. From inside any container, an attacker can escape with just two HTTP POST requests:
import requests
# Step 1: Create a container that binds the host filesystem
requests.post(
"http://192.168.65.7:2375/containers/create",
json={
"Image": "alpine",
"Cmd": ["ls", "/host"],
"HostConfig": {
"Binds": ["/:/host"] # Mount host root into container
}
}
)
# Step 2: Start the container for execution
# (Attacker now has access to host filesystem)
This vulnerability can also be exploited through Server-Side Request Forgery (SSRF) attacks. It exists regardless of whether Enhanced Container Isolation (ECI) is enabled.
The Fix
Update to Docker Desktop 4.44.3 or later.
This version properly secures the Docker Engine API socket, preventing unauthenticated access from within containers.
What You Need to Do
Update Docker Desktop Immediately: If you're on Windows or macOS, update to version 4.44.3 or later.
Check Your Version: Help → Check for Updates (or Docker Desktop → Check for Updates)
Verify the Fix: After updating, the vulnerable socket should no longer be exposed.
🛡️ Security Best Practice: Even with this fix, follow the principle of least privilege. Don't run containers with unnecessary capabilities or host filesystem access.
Migration Guide: What Developers Need to Do
For Docker Desktop Users
- ✅ Update to Docker Desktop 4.44.3 or later (critical for security)
- No other action needed—Engine updates are bundled automatically
For Docker Engine (Linux) Users
- Update your Docker CLI to match your Engine version
- Test your workflows with the containerd image store (opt-in)
- Update Go imports if you consume Docker's Go APIs:
// Before
import "github.com/docker/docker/client"
// After
import "github.com/moby/moby/client"
- Test nftables in non-production environments if you want to provide feedback
- Plan your migration from graph drivers to containerd image store
For Security Teams
- Prioritize Docker Desktop updates to 4.44.3+ (CVE-2025-9074)
- Audit container workloads for any signs of exploitation
- Review firewall rules if using custom iptables configurations
Troubleshooting
"client version X.XX is too old"
Solution: Update your Docker CLI or override the minimum API version (temporary mitigation only):
# Override via environment variable
DOCKER_MIN_API_VERSION=1.24 dockerd
Containerd image store issues
Symptoms: Unexpected behavior with image layers, build caching, or container operations.
Solutions:
- Check if containerd image store is enabled:
docker info | grep "containerd" - Disable if needed (add to daemon.json):
{
"features": {
"containerd-image-store": "disable"
}
}
- Restart Docker:
sudo systemctl restart docker
nftables experimental issues
Symptoms: Network connectivity problems, Docker networks not working.
Solutions:
- Check if nftables is enabled:
docker info | grep firewall - Fall back to iptables by removing the configuration:
{
"firewall-backend": "iptables"
}
- Restart Docker
- Check for IP forwarding:
cat /proc/sys/net/ipv4/ip_forward(should be 1)
Go module import errors
Error: cannot find package "github.com/docker/docker/client"
Solution: Update your import path:
import (
"github.com/moby/moby/client"
"github.com/moby/moby/api/types"
"github.com/moby/moby/api/types/container"
)
Then update your dependencies:
go get github.com/moby/moby@latest
Frequently Asked Questions
Q: Do I need to migrate my existing containers to the containerd image store?
A: No—not yet. Existing installations are not forced to migrate. However, the graph driver backend will be removed in a future release, so you should plan your migration. You can opt-in to test it now.
Q: Is Docker Desktop affected by the API version change?
A: No. Docker Desktop users don't need to take any action—Engine updates are included automatically in Desktop releases.
Q: Should I enable nftables in production?
A: Not yet. It's marked experimental. Test it in non-production environments and provide feedback to the Moby project.
Q: Is Docker Desktop on Linux affected by CVE-2025-9074?
A: No. Docker Desktop on Linux uses a Unix named pipe rather than a TCP socket, so it's not vulnerable under default configurations.
Q: What's the difference between containerd and the containerd image store?
A: Containerd is the container runtime (handles container execution). The containerd image store is a separate component that handles image layer management and content storage. Docker now uses both for a unified architecture.
Q: Will my custom iptables rules break with nftables?
A: Possibly. If you use the DOCKER-USER chain, you'll need to migrate those rules to nftables. See the official documentation for migration instructions.
Q: How do I check if my Docker installation is using containerd image store?
A: Run:
docker info | grep -i containerd
If you see "containerd image store: enabled", you're using it.
Conclusion
Docker Engine v29 is a foundational release that doesn't dazzle with new features but instead builds a more solid future. The key takeaways:
- Update your Docker CLI to avoid API version errors
- Update Docker Desktop to 4.44.3+ immediately—this is critical for security (CVE-2025-9074)
- Understand the containerd image store even if you're not migrating yet
- Update Go imports if you consume Docker's APIs
- Test nftables and provide feedback to shape the future
These changes reflect Docker's broader strategy: align with industry standards (containerd, Go modules), simplify the architecture, and prepare for future innovations. While some changes require action, the long-term benefits—better maintainability, improved interoperability, and new capabilities—make this a worthwhile evolution.
Stay secure, keep your Docker installations updated, and keep experimenting.
Have questions or insights about Docker Engine v29? Share your experience in the comments below.
Top comments (0)