8 min left
1646 words
8 minutes

Docker 29 Broke Traefik — Here's the Fix (and Why It Happened)

Docker 29 Broke Traefik — Here’s the Fix (and Why It Happened)#

The “Everything Is Down” Moment#

You ran apt upgrade on a Sunday evening on your Linux server. Seemed harmless. Docker updated to v29.0.0. You rebooted because why not.

Now every service behind your Traefik reverse proxy returns a 404. Or a 502. Or just… nothing. Your monitoring is screaming. Your personal projects are unreachable. Your CI pipeline is stuck. And if you’re running Coolify, Dokploy, or any platform that bundles Traefik, you can’t even access the management UI to fix it.

You check the Traefik logs and see this, repeating every few seconds:

ERR Failed to retrieve information of the docker client and server host
error="Error response from daemon: client version 1.24 is too old.
Minimum supported API version is 1.44, please upgrade your client
to a newer version" providerName=docker

Your first thought: “I didn’t change anything in Traefik.”

You’re right. You didn’t. Docker changed something under you.

Let me save you the debugging. Here’s the fix.

The 30-Second Fix#

This applies to Linux hosts running Docker Engine directly. If you’re using Docker Desktop (macOS or Windows), you’re not affected — updates are bundled automatically.

If your services are down right now and you need them back immediately, do this:

Edit (or create) /etc/docker/daemon.json:

Terminal window
sudo nano /etc/docker/daemon.json

Add this:

{
"min-api-version": "1.24"
}

If you already have content in daemon.json (storage driver, log driver, etc.), merge the key into the existing object. Don’t overwrite your whole config:

{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"min-api-version": "1.24"
}

The most common mistake is a missing or trailing comma. JSON is strict about this.

Then restart Docker:

Terminal window
sudo systemctl restart docker

Important: Restarting Docker stops all running containers. If your containers have a restart policy (restart: unless-stopped or restart: always), they’ll come back on their own. If not, you’ll need to start them manually:

Terminal window
docker compose up -d

Docker Swarm: This fix works the same on Swarm nodes. Apply it to all managers and workers. Swarm services will reschedule automatically after the daemon restarts.

Rootless Docker? The config file lives at ~/.config/docker/daemon.json and you restart with systemctl --user restart docker.

That’s it. Your services should come back within seconds. Traefik will reconnect to the Docker daemon, discover your containers, and routes will light up again.

Verifying it worked#

Check Traefik’s logs:

Terminal window
docker logs traefik --tail 20

You should no longer see the client version 1.24 is too old error. If you see Configuration received from provider docker, that’s a positive confirmation (this message only appears at INFO log level, which may not be your default).

The strongest verification is the API version check below.

Confirm your Docker API versions:

Terminal window
docker version --format '{{.Server.MinAPIVersion}}'

This should now return 1.24 instead of 1.44.

Why this works: The min-api-version setting overrides Docker’s built-in floor. It tells the daemon to accept connections from clients using API version 1.24 and above, restoring the backward compatibility that Docker 29 removed. This config change keeps Docker 29 fully operational while re-enabling communication with older API clients. You’re still running Docker 29 with all its features — you’ve just told it to accept a wider range of client versions.

Is this safe? For now, yes. This setting only changes how Docker negotiates API versions with clients. The API version is a negotiation protocol that controls feature detection between client and server. It doesn’t touch encryption or authentication. The risk is that older API clients might miss newer fields or features, but Traefik only needs to read container labels and inspect networks. It doesn’t need API 1.44 for that.

The Real Fix: Update Traefik#

The daemon.json workaround is a bandage. The actual fix is updating Traefik to v3.6.1 or later.

Traefik v3.6.1, released shortly after this incident, added automatic Docker API version negotiation. Instead of hardcoded v1.24, Traefik now queries the daemon for its supported version range and picks the highest mutually compatible version. This is how the Docker SDK is supposed to work.

If you manage Traefik directly (docker-compose, Dockerfile, etc.), change your image tag:

services:
traefik:
image: traefik:v3.6.1

Or pull the latest:

Terminal window
docker pull traefik:v3.6.1

Then restart:

Terminal window
docker compose up -d traefik

If you’re on the older standalone docker-compose, the command is docker-compose up -d traefik.

Once Traefik is on 3.6.1+, you can remove the "min-api-version" workaround from daemon.json and restart Docker again. Everything will keep working because Traefik now negotiates the API version correctly on its own.

If you can’t update Traefik directly#

If you’re running a platform that bundles Traefik (Coolify, Dokploy, Appwrite, CapRover), you might not control the Traefik image version. In that case:

  1. Check if your platform has an update. Most of them shipped patches within days.
  2. Use the daemon.json workaround until the platform updates its bundled Traefik.
  3. Check the platform’s GitHub issues. This broke so many deployments that every affected platform has a thread about it.

What Actually Happened#

Let me explain the technical chain of events, because understanding it helps you prevent similar breakages.

Docker’s API version floor#

Docker Engine exposes a versioned API. Clients (CLI, SDK, third-party tools) negotiate which version to use during the initial handshake. Before Docker 29, the daemon supported API versions going all the way back to v1.24, which was introduced with Docker 1.12 in 2016. Nearly a decade of backward compatibility.

With Docker Engine v29.0.0 (released November 10, 2025), Docker raised the minimum supported API version to v1.44. API v1.44 corresponds to Docker Engine v25, released in late 2023.

This was deliberate and documented. Docker’s deprecation policy states that API versions are supported for a limited number of major releases. API 1.24 had been deprecated for years. Docker 29 finally enforced the deprecation.

The result: any tool compiled against an older Docker SDK that defaults to API v1.24 as its negotiation floor gets rejected immediately. No fallback. No graceful degradation. A hard error: client version 1.24 is too old.

Why Traefik specifically exploded#

Traefik uses Docker’s official Go SDK (github.com/docker/docker/client) for container discovery. It reads container labels, figures out routing rules, and dynamically updates its configuration.

The problem is in how the Go Docker SDK initializes. When you create a new client with client.NewClientWithOpts(), the SDK defaults to negotiating from API v1.24. This has been the SDK’s default since it was written. It was never a problem because Docker always accepted v1.24.

Docker 29 stopped accepting it. The negotiation fails before Traefik can even list containers. No containers discovered means no routes configured means every request hits a 404 or 502.

This affected all Traefik versions through v3.6.0, including v2.x. Traefik was using an SDK default (API v1.24) that Docker 29 no longer accepts.

It’s Not Just Traefik#

Traefik got the most attention because a broken reverse proxy takes down everything behind it. But Docker 29’s API floor broke a wide range of tools:

ToolWhat BrokeFix
Traefik (v3.6.0 and earlier)Container discovery, all routingUpdate to v3.6.1+
Portainer (before v2.33.5)Can’t connect to Docker environmentsUpdate to v2.33.5+ (LTS) or v2.36.0+ (STS)
WatchtowerCan’t query containers for updatesSwitch to nickfedor/watchtower (original containrrr/watchtower is unmaintained)
LazyDockerDocker connection failsUpdate to v0.24.2+
DokployBundled Traefik failsUpdate Traefik image to v3.6.1
CoolifyBundled Traefik failsCheck for Coolify update
AppwriteBundled Traefik v2.11 failsUpdate to Appwrite version using Traefik v3
JetBrains IDEsDocker plugin throws 400 errorsUpdate IDE / Docker plugin
Spring Boot (Testcontainers)docker-java defaults to API v1.32Update to Spring Boot 3.5.8+ (includes workaround), or set api.version=1.44 in docker-java.properties
SwarmpitDocker API calls failNo fix: project is archived
CapRoverDocker API connectivityCheck for update
CasaOSDocker API connectivityCheck for update
cAdvisorMetrics collection stopsUpdate to v0.53.0+

The pattern repeats across every entry: the tool uses a Docker SDK with a hardcoded minimum version below 1.44, Docker 29 rejects the connection, and the tool can’t communicate with the daemon.

Swarmpit is the saddest entry on that list. The project is archived. No fix is coming. Docker 29 finished what abandonment started.

Timeline#

For the record, here’s how this played out:

  • Nov 10, 2025 — Docker Engine v29.0.0 released. Minimum API version raised to v1.44. Traefik immediately breaks for everyone who auto-updates.
  • Nov 10-11, 2025 — Reports flood in. Traefik GitHub issue #12253 is filed. The Docker Community Forums thread explodes. The Traefik community forum fills up. Coolify, Dokploy, and Appwrite all see the same issue.
  • Nov 11, 2025 — Community identifies the daemon.json workaround and the DOCKER_MIN_API_VERSION environment variable as immediate workarounds.
  • Nov 12, 2025 — Traefik maintainer PR #12256 adds automatic API version negotiation. Community test builds appear on Docker Hub.
  • Nov 13-14, 2025 — Traefik v3.6.1 released with the fix. Portainer ships v2.33.5 and v2.36.0 with updated API support. LazyDocker ships v0.24.2.
  • Nov 2025 onward — The rest of the tooling world catches up. Spring Boot, JetBrains, and others ship fixes over the following weeks.

From “everything is broken” to “official fix available”: roughly 48 hours. Solid open-source incident response. But if you were one of the people whose services went down on a Sunday night, it probably felt a lot longer.

Takeaways#

For your infrastructure#

Pin your Docker version in production. Docker 29’s release notes documented the API version change. But if Docker auto-updates via your package manager (as it does on Ubuntu with the official repository), you get the breaking change whether you read the notes or not.

On Ubuntu/Debian:

Terminal window
sudo apt-mark hold docker-ce docker-ce-cli containerd.io

When you’re ready to upgrade, unpin:

Terminal window
sudo apt-mark unhold docker-ce docker-ce-cli containerd.io

Pin your Traefik version too. Using traefik:latest means you get updates automatically, which is usually fine, but it also means you can’t predict when behavior changes. Use explicit version tags like traefik:v3.6.1.

Keep a daemon.json backup. This file is tiny but critical. If you have it backed up or version-controlled, you can apply the workaround in under a minute instead of googling for it.

For the broader picture#

A huge number of Docker-adjacent tools depended on an API version Docker deprecated years ago. The SDK default of v1.24 was never updated because Docker was always backward-compatible. Tools that were actively maintained shipped fixes within days. Tools that weren’t (Swarmpit, older CasaOS setups) are now permanently broken on Docker 29+.

The min-api-version escape hatch is Docker acknowledging the pain with a temporary lever. Eventually, even that setting may go away.

If you maintain a tool that talks to Docker, check your SDK’s default API version negotiation. If it’s hardcoded to a minimum, make it dynamic. The Traefik PR that fixed this was a few dozen lines of code.


Update Traefik. Pin your Docker version. The order is up to you.

Docker 29 Broke Traefik — Here's the Fix (and Why It Happened)
https://corentings.dev/blog/docker-29-traefik-fix/
Author
Corentin Giaufer Saubert
Published at
2026-05-04
License
CC BY-NC-SA 4.0
Share this post