"\n# Docker Engine v29: A Foundation Release That Shapes the Future\n\nDocker 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.\n\nIn 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.\n\n---\n\n## Background: Why This Release Matters\n\nDocker 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.\n\nDocker 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.\"\n\nIf 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.\n\n---\n\n## 1. Minimum API Version Update\n\n### What Changed\n\nDocker 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.\n\nIf you're using an outdated Docker client, you'll see this error:\n\n
\nError response from daemon: client version 1.43 is too old.\nMinimum supported API version is 1.44, please upgrade your client to a newer version\n
\n\n### Why This Matters\n\nDocker 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.\n\n### How to Handle It\n\n*Option 1: Upgrade your Docker client (Recommended)\n\nSimply update your Docker CLI to match your Docker Engine version:\n\n
bash\n# Check your current versions\ndocker version\n\n# Update Docker Engine (example for Ubuntu/Debian)\nsudo apt update\nsudo apt upgrade docker.io\n
\n\nOption 2: Override the minimum API version (Not recommended for production)\n\nIf you absolutely must use an older client, you can override the minimum API version—though Docker explicitly warns against this for production environments.\n\nUsing environment variable:\n\n
bash\nDOCKER_MIN_API_VERSION=1.24 dockerd\n
\n\nUsing daemon.json:\n\n
json\n{\n \"min-api-version\": \"1.24\"\n}\n
\n\nSave this to /etc/docker/daemon.json and restart Docker:\n\n
bash\nsudo systemctl restart docker\n
\n\n> ⚠️ **Warning: Using an older API version may expose you to security vulnerabilities and compatibility issues. Only use this as a temporary mitigation.\n\n---\n\n## 2. Containerd Image Store Becomes the Default\n\n### The Big Shift\n\nStarting with Docker Engine v29, the **containerd image store* is now the default for new installations. This is a fundamental architectural change.\n\nPreviously, 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.\n\nNow, both execution and storage use containerd.\n\n### What This Means in Practice\n\nFor new installations, Docker will use containerd's image store by default. You might notice:\n\n- Different behavior in docker images and docker build\n- Changes in how layer caching works\n- Some container operations may behave slightly differently\n\n### Opting Out (If Needed)\n\nIf 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:\n\n
json\n{\n \"features\": {\n \"containerd-image-store\": \"disable\"\n }\n}\n
\n\nThen restart Docker:\n\n
bash\nsudo systemctl restart docker\n
\n\n### Why This Change Matters\n\n1. Simplified Architecture: Both execution and storage now use containerd, reducing internal complexity and maintenance burden.\n\n2. Unlocks New Features: This enables future innovations like:\n - Snapshotter innovations\n - Lazy pulling of image content (like BuildKit's content-aware builds)\n - Remote content stores\n - Peer-to-peer image distribution\n\n3. Ecosystem Alignment: Docker Engine now matches how Kubernetes and other containerd-based platforms work, improving interoperability.\n\n4. Future-Proofing: The graph driver backend will eventually be removed entirely.\n\n### Migration Path for Existing Users\n\nHere'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:\n\n
bash\n# Enable containerd image store (opt-in for existing installations)\ndocker features enable containerd-image-store\n
\n\nDocker 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.\n\n---\n\n## 3. Moby Migrates to Go Modules\n\n### What Changed\n\nThe 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.\n\n### Important: Module Path Change\n\nIf you're importing Docker packages in your Go projects, you need to update your imports:\n\n
go\n// OLD (no longer receives updates)\nimport \"github.com/docker/docker/client\"\n\n// NEW (must use this going forward)\nimport \"github.com/moby/moby/client\"\n
\n\n### Why This Matters\n\nGo 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:\n\n- Eliminates \"constant maintenance churn\" to work around tooling assumptions\n- Provides clearer workflows for contributors\n- Improves compatibility with modern Go tools\n- Makes the Moby codebase easier to consume and integrate with\n\n### What This Means for You\n\n*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.\n\n*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.\n\n---\n\n## 4. Experimental Support for nftables\n\n### What Changed\n\nDocker Engine v29 introduces experimental support for nftables as an alternative to iptables for managing firewall rules on Linux.\n\n### Why This Matters\n\nCurrently, 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.\n\nHowever:\n- Linux distributions are beginning to deprecate iptables support\n- The translation layer adds overhead and complexity\n- nftables offers more modern features and better performance\n\n### How to Enable nftables Support\n\nStart Docker with the --firewall-backend=nftables flag:\n\n
bash\ndockerd --firewall-backend=nftables\n
\n\nOr add it to your daemon configuration:\n\n
json\n{\n \"firewall-backend\": \"nftables\"\n}\n
\n\n### Important Considerations\n\n1. DOCKER-USER Chain Migration: If you use the DOCKER-USER iptables chain for custom rules, you'll need to migrate it to nftables. See the official documentation for migration steps.\n\n2. Firewalld Integration: On hosts using firewalld, Docker will still set up firewalld zones and policies, but will create nftables rules directly.\n\n3. 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.\n\n4. Experimental: This feature is marked experimental. Don't deploy it in production without thorough testing.\n\n5. IP Forwarding: After enabling nftables and rebooting, you may need to re-enable IP forwarding on the host:\n\n
bash\n# Check current setting\ncat /proc/sys/net/ipv4/ip_forward\n\n# Enable if needed (make persistent in /etc/sysctl.conf)\necho 1 > /proc/sys/net/ipv4/ip_forward\n
\n\n### What's Coming\n\nIn 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.\n\n---\n\n## 5. Critical Security: CVE-2025-9074 and Docker Desktop 4.44.3\n\n### The Vulnerability\n\n*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).\n\n*Discovered by: Felix Boulet and Philippe Dugre (mid-2025)\n\n### What Was Wrong\n\nDocker 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.\n\n### Impact\n\nWindows* (Critical):\n- Complete host takeover with administrator privileges possible\n- Attackers can bind the host's filesystem (e.g., C:) into a new container\n- Execute arbitrary code on the host\n\n*macOS* (High):\n- Docker manipulation and backdooring is possible\n- Additional permission prompts limit (but don't eliminate) the risk\n\n*Linux* (Not vulnerable by default):\n- Docker Desktop on Linux uses a Unix named pipe for the Docker Engine API\n- The TCP socket vulnerability doesn't exist\n\n### Exploitation\n\nThe attack is alarmingly simple. From inside any container, an attacker can escape with just two HTTP POST requests:\n\n
python\nimport requests\n\n# Step 1: Create a container that binds the host filesystem\nrequests.post(\n \"http://192.168.65.7:2375/containers/create\",\n json={\n \"Image\": \"alpine\",\n \"Cmd\": [\"ls\", \"/host\"],\n \"HostConfig\": {\n \"Binds\": [\"/:/host\"] # Mount host root into container\n }\n }\n)\n\n# Step 2: Start the container for execution\n# (Attacker now has access to host filesystem)\n
\n\nThis vulnerability can also be exploited through Server-Side Request Forgery (SSRF) attacks. It exists regardless of whether Enhanced Container Isolation (ECI) is enabled.\n\n### The Fix\n\n*Update to Docker Desktop 4.44.3 or later.\n\nThis version properly secures the Docker Engine API socket, preventing unauthenticated access from within containers.\n\n### What You Need to Do\n\n1. **Update Docker Desktop Immediately: If you're on Windows or macOS, update to version 4.44.3 or later.\n\n2. **Check Your Version: Help → Check for Updates (or Docker Desktop → Check for Updates)\n\n3. **Verify the Fix: After updating, the vulnerable socket should no longer be exposed.\n\n> 🛡️ **Security Best Practice: Even with this fix, follow the principle of least privilege. Don't run containers with unnecessary capabilities or host filesystem access.\n\n---\n\n## Migration Guide: What Developers Need to Do\n\n### For Docker Desktop Users\n\n- ✅ Update to Docker Desktop 4.44.3 or later (critical for security)\n- No other action needed—Engine updates are bundled automatically\n\n### For Docker Engine (Linux) Users\n\n1. **Update your Docker CLI* to match your Engine version\n2. Test your workflows with the containerd image store (opt-in)\n3. Update Go imports if you consume Docker's Go APIs:\n
go\n // Before\n import \"github.com/docker/docker/client\"\n \n // After \n import \"github.com/moby/moby/client\"\n
\n4. Test nftables in non-production environments if you want to provide feedback\n5. Plan your migration from graph drivers to containerd image store\n\n### For Security Teams\n\n1. Prioritize Docker Desktop updates to 4.44.3+ (CVE-2025-9074)\n2. Audit container workloads for any signs of exploitation\n3. Review firewall rules if using custom iptables configurations\n\n---\n\n## Troubleshooting\n\n### \"client version X.XX is too old\"\n\n*Solution: Update your Docker CLI or override the minimum API version (temporary mitigation only):\n\n
bash\n# Override via environment variable\nDOCKER_MIN_API_VERSION=1.24 dockerd\n
\n\n### Containerd image store issues\n\nSymptoms: Unexpected behavior with image layers, build caching, or container operations.\n\nSolutions:\n1. Check if containerd image store is enabled: docker info | grep \"containerd\"\n2. Disable if needed (add to daemon.json):\n
json\n {\n \"features\": {\n \"containerd-image-store\": \"disable\"\n }\n }\n
\n3. Restart Docker: sudo systemctl restart docker\n\n### nftables experimental issues\n\nSymptoms: Network connectivity problems, Docker networks not working.\n\nSolutions:\n1. Check if nftables is enabled: docker info | grep firewall\n2. Fall back to iptables by removing the configuration:\n
json\n {\n \"firewall-backend\": \"iptables\"\n }\n
\n3. Restart Docker\n4. Check for IP forwarding: cat /proc/sys/net/ipv4/ip_forward (should be 1)\n\n### Go module import errors\n\nError: cannot find package \"github.com/docker/docker/client\"\n\nSolution: Update your import path:\n\n
go\nimport (\n \"github.com/moby/moby/client\"\n \"github.com/moby/moby/api/types\"\n \"github.com/moby/moby/api/types/container\"\n)\n
\n\nThen update your dependencies:\n\n
bash\ngo get github.com/moby/moby@latest\n
\n\n---\n\n## Frequently Asked Questions\n\n### Q: Do I need to migrate my existing containers to the containerd image store?\n\nA: 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.\n\n### Q: Is Docker Desktop affected by the API version change?\n\nA: No. Docker Desktop users don't need to take any action—Engine updates are included automatically in Desktop releases.\n\n### Q: Should I enable nftables in production?\n\nA: Not yet. It's marked experimental. Test it in non-production environments and provide feedback to the Moby project.\n\n### Q: Is Docker Desktop on Linux affected by CVE-2025-9074?\n\nA: No. Docker Desktop on Linux uses a Unix named pipe rather than a TCP socket, so it's not vulnerable under default configurations.\n\n### Q: What's the difference between containerd and the containerd image store?\n\nA: 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.\n\n### Q: Will my custom iptables rules break with nftables?\n\nA: Possibly. If you use the DOCKER-USER chain, you'll need to migrate those rules to nftables. See the official documentation for migration instructions.\n\n### Q: How do I check if my Docker installation is using containerd image store?\n\nA: Run:\n
bash\ndocker info | grep -i containerd\n
\n\nIf you see \"containerd image store: enabled\", you're using it.\n\n---\n\n## Conclusion\n\nDocker Engine v29 is a foundational release that doesn't dazzle with new features but instead builds a more solid future. The key takeaways:\n\n1. **Update your Docker CLI* to avoid API version errors\n2. Update Docker Desktop to 4.44.3+ immediately—this is critical for security (CVE-2025-9074)\n3. Understand the containerd image store even if you're not migrating yet\n4. Update Go imports if you consume Docker's APIs\n5. Test nftables and provide feedback to shape the future\n\nThese 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.\n\nStay secure, keep your Docker installations updated, and keep experimenting.\n\n---\n\n*Have questions or insights about Docker Engine v29? Share your experience in the comments below.*\n"
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)