DevOps

How to Upgrade to Docker Engine 29.9.1: Eight Security Fixes and a Test Plan

Docker Engine 29.9.0 and 29.9.1 landed within a week, bundling HTTP/2 daemon fixes and three containerd advisories. Here is how to roll them out safely.

Paige Donnelly

Senior Backend Engineer

Published 7 min read
Luminous night view of a bustling industrial port with cargo ships.
On this page 9 sections

Docker Engine 29.9.1, released October 14, 2026, updates containerd to v2.4.2 to fix three advisories, two of which can crash containerd and one that can fill a host disk. It follows 29.9.0, which patched four HTTP/2 denial-of-service flaws in the daemon. Upgrade to 29.9.1 directly and test pulls, networking and rootless setups.

Docker Engine 29.9.1 is the kind of release that is easy to postpone and expensive to ignore. It arrived on October 14, only six days after 29.9.0, and the two releases together carry eight security fixes. Most of them let a remote party crash a service or exhaust a host resource.

This guide is for engineers who run Docker on build servers, CI runners and production hosts. It lists what each release fixed, shows a safe rollout order, and flags the changes that can surprise you. Teams that already pinned their pipelines, as in our workflow lockfile guide, will find the second half of this plan familiar. Backtrace reviews infrastructure patches by asking what breaks when you apply them.

What did Docker Engine 29.9.1 fix?

A colossal cargo ship loaded with containers navigates through calm waters against a vibrant sunset sky.

Docker Engine 29.9.1 updates containerd to v2.4.2, which closes three security issues. According to Docker's release notes for Engine 29, all three involve a crafted image or an untrusted registry.

The table below summarizes them.

What did Docker Engine 29.9.1 fix?
AdvisoryImpact
CVE-2026-95839A malformed digest in a child descriptor's manifest subject annotation could crash containerd during a pull or import
GHSA-8647-2jxj-p2rcA crafted Content-Length from an untrusted registry could crash containerd when parallel layer fetching was enabled
GHSA-hc94-p972-ch66Crafted images or malicious registries could exhaust host disk space, because layer data was not capped at the declared size

None of these needs local access. They need your host to pull from a source the attacker controls or influences. That makes them most relevant to build farms, CI systems and any platform that pulls images from outside your own registry.

The release also carries ordinary bug fixes. Examples include a daemon panic with the fluentd log driver and a failure in docker ps -s when one container's size cannot be computed.

What did 29.9.0 fix a week earlier?

Detailed view of network cables plugged into a server rack in a data center.

Release 29.9.0, dated October 8, carried the daemon-side fixes. The release notes list four HTTP/2 flaws that let a client crash the daemon or burn resources.

  1. CVE-2026-97032: changing the HPACK header table size during requests could crash the daemon.
  2. CVE-2026-78659: declaring many fields in a Trailer header could exhaust memory.
  3. CVE-2026-78663: resetting streams could exceed the connection-level flow control limit.
  4. CVE-2026-78669: repeatedly changing the initial window size could cause excessive CPU use.

A fifth item, CVE-2026-56857, applies only to Windows. A junction in the data root could cause the daemon to create directories outside it. Linux-only fleets can skip that one.

The same Go networking library update, golang.org/x/net v0.60.0, also covers the deprecated /grpc endpoint and BuildKit's frontend gRPC server. If you expose the Docker API over TCP, treat these as urgent. If the socket is local only, the exposure is smaller.

The CPU issue also appeared in a weekly package management roundup, which noted that Terraform and OpenTofu fixed the same class of problem. That is a hint of how widely the Go library flaw spread.

Should you skip 29.9.0 and go straight to 29.9.1?

Yes, go straight to 29.9.1 if your package manager offers it. Version 29.9.1 contains the 29.9.0 fixes plus the containerd update, so installing 29.9.0 first only adds a restart. Each restart on a busy host costs you a drain, a health check and a window.

The exception is a staged environment where you already validated 29.9.0. In that case, the incremental step to 29.9.1 is small and you can treat it as a patch on a known base. Do not leap two minor versions in production without a test pass.

At Backtrace, we default to the newest patch release of the line you already run. It saves restarts, and it avoids the situation where a host sits on an intermediate version that nobody is tracking.

How do you check what your hosts are running now?

An IT professional operates a computer in a server room, managing network systems and connected devices.

Start by finding your current versions. A quick inventory beats guessing, and the commands are short. Run them on each host, or push them through your configuration tool.

text
docker version --format '{{.Server.Version}}'
docker info --format '{{.ServerVersion}} {{.OperatingSystem}}'
containerd --version
runc --version

Record four things per host: the Docker Engine version, the containerd version, the runc version and whether the host runs rootless mode. The runc version matters for one fix in 29.9.1, described below.

Then sort hosts by exposure. Hosts that pull images from public registries or run builds for outside contributors come first. Hosts that only pull from your own private registry come second. An internal-only host still needs the patch, but it is not the first fire.

Finally, list any host with the API exposed on a TCP port. Those are the machines the HTTP/2 fixes from 29.9.0 protect most.

What is a safe rollout order for the upgrade?

A safe rollout moves from lowest to highest risk and checks the same things at each stage. This order has worked well for us on mixed fleets.

  1. Upgrade one CI runner and run a full build with a cold image cache.
  2. Upgrade a staging host and run your normal deploy through it.
  3. Upgrade a small slice of production, drained first.
  4. Watch pulls, restarts and disk use for a day.
  5. Roll the rest in batches, keeping one host on the old version as a fallback.

Drain each host before you restart the daemon. Unless you enable live restore, restarting the Docker daemon stops running containers, so plan for that. Check your own settings before assuming either behavior.

Keep the rollback path simple. Pin the package version in your configuration tool so a failed host can return to the last good build in minutes. A rollback you have never tested is a hope, not a plan.

Which changes can surprise you after upgrading?

Miniature caution cone on a computer keyboard symbolizing data security and control.

Three changes are worth a test before you roll widely. The first is the lazy-pull default introduced in 29.9.0. It controls whether docker pull skips layers the snapshotter already provides, and it is on by default for nydus, overlaybd, soci and stargz. If you use one of those remote snapshotters, review the setting.

The second is the rootless fix in 29.9.1. The --domainname option now works with user namespaces and rootless mode, but it needs an OCI runtime that supports the domainname field, which means runc v1.2.0 or later. An older runc will not benefit from the fix.

The third is stricter validation. In 29.9.1, --link-local-ip rejects addresses outside 169.254.0.0/16 and fe80::/10. Previously such an address caused containers to fail to start. Now you get a clear error, which may reveal a bad value in an old compose file.

Firewall users should also read the networking notes. Bridge interfaces are no longer added to firewalld's docker zone when iptables and ip6tables are both disabled, and bridge networks bound to a non-docker zone now restore on daemon startup.

How do you verify the patch worked?

Verification has two parts: confirm versions, then exercise the paths the fixes touched. Start with the version commands above and confirm containerd reports v2.4.2.

Then test pulls. Pull a large multi-layer image from your registry, pull one through a mirror, and run an import from a tarball. These cover the code paths in the three containerd advisories. Watch memory and disk use during the pull.

Test networking next. Start a compose stack, confirm published ports work, and if you use encrypted overlay networks, check that nodes rejoin cleanly. Release 29.9.0 fixed several overlay problems, including encrypted traffic possibly being sent in cleartext after errors programming kernel encryption.

Finally, pair patching with scanning. A software composition scan catches vulnerable base images, while host patching covers the engine itself. You need both, because they protect different layers.

Write the result down. A one-line note with version, date and test outcome saves hours during the next audit.

How does patching fit with a busy delivery pipeline?

Patching competes with feature work, and CI capacity is the usual bottleneck. If builds already queue for an hour, a runner upgrade feels expensive. That tension is real, as we explained in our look at the CI bottleneck.

The practical fix is to schedule infrastructure patches as normal work. Put the upgrade on the board, assign an owner and give it a date. Patches that live only in someone's memory slip every time a release deadline arrives.

Automate the boring parts. Use your configuration tool to pin versions, run the inventory commands and report drift. A dashboard showing hosts behind the latest patch turns a vague worry into a number the team can reduce.

Finally, agree on a patch window with your product owners. A short weekly slot for low-risk upgrades beats emergency maintenance at midnight.

Your Docker 29.9.1 upgrade checklist

Docker Engine 29.9.1 is a worthwhile patch. It folds the 29.9.0 HTTP/2 fixes together with a containerd update that closes three pull-time advisories. The risk of waiting is highest on hosts that pull from outside your control.

Inventory your versions today, upgrade one runner, run a cold-cache build, and then widen the rollout. Check your runc version and the lazy-pull setting before you finish. Backtrace will keep covering the patches that matter for production infrastructure.

What does Docker Engine 29.9.1 fix?
It updates containerd to v2.4.2 and closes three advisories: CVE-2026-95839, GHSA-8647-2jxj-p2rc and GHSA-hc94-p972-ch66. Two can crash containerd through crafted image data or a hostile registry, and one can exhaust host disk space. It also fixes several bugs in networking, rootless mode and the fluentd driver.
Do I need to install 29.9.0 before 29.9.1?
No. Release 29.9.1 includes the 29.9.0 fixes, so you can upgrade straight to it. Installing 29.9.0 first only adds an extra daemon restart. If you already validated 29.9.0 in staging, the step to 29.9.1 is a small patch on a known base.
Why does the domainname fix need runc 1.2.0?
The 29.9.1 fix makes the domainname option work with user namespaces and rootless mode, but it relies on an OCI runtime that supports the domainname field. Docker's notes say that means runc v1.2.0 or later. Check your runc version with runc --version before expecting the fix to apply.
Does restarting the Docker daemon stop my containers?
By default, yes, unless you have enabled live restore. Drain each host before you upgrade, and check your daemon settings first. Live restore can keep containers running during a daemon restart, but test it on a staging host, because behavior depends on your configuration and workloads.

Written by

Paige Donnelly

Senior Backend Engineer

8+ years experience

Paige Donnelly is a senior backend engineer who has spent the last eight years working on distributed systems, first at a mid-size fintech and then leading a payments infrastructure team through a migration from a monolith to event-driven services. She's on the losing end of more 3am pages than she'd like to admit, which is why she writes about observability, deployment safety, and API design with an eye toward what actually breaks in production rather than what looks good in a conference talk. She contributes to a couple of open-source CLI tools in her spare time and still refuses to use a debugger for anything she can solve with well-placed logs.

Credentials

  • 8 years in backend and distributed systems engineering
  • Former tech lead, payments infrastructure at a Series D fintech
  • Contributor to several open-source developer tooling projects