You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Docker Desktop 4.70.0 httpproxy severs long HTTPS CONNECT tunnels mid-upload (breaks large docker push)
Version
Docker Desktop: 4.70.0 (Docker Engine 29.4.0, Client 29.4.0, API 1.54)
macOS: 26.4.1 (Tahoe, Build 25E253, Darwin 25.4.0)
Hardware: Intel Core i9-9980HK (x86_64)
Summary
Docker Desktop's internal httpproxy component (running on the VM gateway at 192.168.65.1:3128) silently closes the write pipe for long-lived HTTPS CONNECT tunnels after roughly 7–10 minutes or ~500–800 MB of data transferred. This breaks docker push and docker buildx build --push for any image containing a large layer.
…which surfaces to the user as either use of closed network connection (buildx) or failed to copy: failed to do request: Put <registry-url> (classic push).
This is a regression — the same workflow worked on Docker Desktop 4.69.x (engine 29.3.0) against the same registry over the same network.
Prior art
'Broken Pipe' Error When Pushing Image #7349 ('Broken Pipe' Error When Pushing Image, 4.31.0, closed) — same exact error fingerprint (write tcp 192.168.65.3:<port>->192.168.65.1:3128: write: broken pipe) reported against Docker Hub. Closed without a real fix because the reporter switched networks and it went away. That report was never properly root-caused; this is likely the same underlying httpproxy pipe-handling bug resurfacing in 4.70.0.
Filing this new issue rather than reopening #7349 because (a) different version, (b) we have a confirmed bypass workaround, (c) we have a specific reproducer and narrowed root cause to the httpproxy component.
Expected behavior
docker push of a multi-GB image to a remote registry completes successfully, limited only by upload bandwidth.
Actual behavior
Small blobs (config, manifests, <~100 MB layers) push successfully.
Large blobs (~500 MB+) fail after 7–10 minutes regardless of the actual available bandwidth.
httpproxy.log reports the CONNECT tunnel as successful after <N>m with <bytes> transferred — but the byte count never reaches the full layer size, and dockerd sees a broken pipe at the same wall-clock moment.
Separately (likely a distinct bug in the 29.4.0 client), progress output for large blobs stays on Waiting indefinitely — the Pushing <percent>% lines never appear. This isn't the root cause but makes the problem look worse than it is during diagnosis.
Minimal reproduction
# Generate a fresh 1 GB random-data image (won't dedupe in any registry)
mkdir -p /tmp/push-test &&cd /tmp/push-test
dd if=/dev/urandom of=blob.bin bs=1m count=1024
cat > Dockerfile <<EOFFROM scratchCOPY blob.bin /EOF
docker buildx build --platform linux/amd64 --load -t <your-registry>/push-test:latest .# Push — will fail after 7–10 min with broken pipe
docker push <your-registry>/push-test:latest
Expected: completes in <image-size> / <upload-bandwidth> seconds.
Actual: fails with broken pipe or closed network connection before completion.
Registry used when filing: Oracle Cloud Infrastructure Registry (phx.ocir.io). Presumably reproduces against any remote registry; please test others.
Evidence
dockerd client error
failed to copy: failed to do request: Put "https://<registry>/v2/.../blobs/uploads/<uuid>?digest=sha256:...":
write tcp 192.168.65.3:61564->192.168.65.1:3128: write: broken pipe
req 443 HTTP CONNECT <registry>:443: successful after 6m46.966798846s with 536301749 bytes transferred (0 remaining in-progress HTTP requests)
The "successful after" entry appears at the exact moment dockerd reports the broken pipe, with only 536 MB transferred of a 1 GB layer.
dockerd VM log
Shows matching use of closed network connection entries for grpc and api-proxy streams at the same timestamp.
Workaround
Add the destination registry to Docker Desktop's Containers Proxy bypass list:
Settings → Resources → Proxies
Toggle Manual proxy configuration ON
Under Containers Proxy (not "Docker Desktop Proxy")
Leave HTTP/HTTPS fields blank
In Bypass proxy settings for these hosts & domains, enter the registry hostname(s), e.g. *.ocir.io,phx.ocir.io
Apply & Restart
After this, httpproxy.log emits container via direct connection because matches container settings exclude and dockerd connects directly to the registry without routing through 192.168.65.1:3128. The same 1 GB push completes in ~5 min 20 s on the same machine / network / registry.
What's NOT the cause (ruled out during investigation)
I spent several hours narrowing this down; hopefully saves triage time:
Registry outage / rate limiting — Ruled out: small HTTPS requests to same registry (<200 ms TTFB) and image pulls succeed during the failing window. Other laptops in the same region push fine.
Buildx / BuildKit specifically — Ruled out: classic docker push (no buildx, no exporter) has the same failure. It's daemon-wide, not buildx-specific.
gvisor VM network stack — Ruled out: created a buildkit container with --driver-opt network=host (bypasses gvisor for the container); same failure pattern persisted at the httpproxy layer.
macOS Tahoe ECN default (net.inet.tcp.ecn_initiate_out=1) — Ruled out: sudo sysctl -w net.inet.tcp.ecn_initiate_out=0 did not change the failure.
macOS TCP stack broadly — Ruled out: curl uploads from the Mac host (bypassing Docker entirely) to Cloudflare complete successfully; SSH uploads to a VM in the same region complete successfully. Only traffic flowing through dockerd → Docker Desktop httpproxy → destination fails.
Upload bandwidth limit — Ruled out: Cloudflare speed-test upload at 11 Mbps works cleanly; no ISP throttle.
Docker Desktop state corruption — Ruled out: quit/relaunch Docker Desktop, restart Mac; same failure.
Signal for the fix
The bypass workaround confirms the bug is specifically in how httpproxy handles long HTTPS CONNECT tunnels when it's in the path. It's not a general networking issue in Docker Desktop — only this specific code path. A likely candidate area is an idle-timer or write-buffer limit in the CONNECT-tunnel handling code that regressed between 4.69.x and 4.70.0.
Happy to provide additional diagnostics or test a candidate fix.
Docker Desktop 4.70.0 httpproxy severs long HTTPS CONNECT tunnels mid-upload (breaks large
docker push)Version
Summary
Docker Desktop's internal
httpproxycomponent (running on the VM gateway at192.168.65.1:3128) silently closes the write pipe for long-lived HTTPS CONNECT tunnels after roughly 7–10 minutes or ~500–800 MB of data transferred. This breaksdocker pushanddocker buildx build --pushfor any image containing a large layer.The dockerd daemon inside the VM reports:
…which surfaces to the user as either
use of closed network connection(buildx) orfailed to copy: failed to do request: Put <registry-url>(classic push).This is a regression — the same workflow worked on Docker Desktop 4.69.x (engine 29.3.0) against the same registry over the same network.
Prior art
write tcp 192.168.65.3:<port>->192.168.65.1:3128: write: broken pipe) reported against Docker Hub. Closed without a real fix because the reporter switched networks and it went away. That report was never properly root-caused; this is likely the same underlying httpproxy pipe-handling bug resurfacing in 4.70.0.Filing this new issue rather than reopening #7349 because (a) different version, (b) we have a confirmed bypass workaround, (c) we have a specific reproducer and narrowed root cause to the
httpproxycomponent.Expected behavior
docker pushof a multi-GB image to a remote registry completes successfully, limited only by upload bandwidth.Actual behavior
httpproxy.logreports the CONNECT tunnel assuccessful after <N>m with <bytes> transferred— but the byte count never reaches the full layer size, and dockerd sees abroken pipeat the same wall-clock moment.Waitingindefinitely — thePushing <percent>%lines never appear. This isn't the root cause but makes the problem look worse than it is during diagnosis.Minimal reproduction
Expected: completes in
<image-size> / <upload-bandwidth>seconds.Actual: fails with
broken pipeorclosed network connectionbefore completion.Registry used when filing: Oracle Cloud Infrastructure Registry (
phx.ocir.io). Presumably reproduces against any remote registry; please test others.Evidence
dockerd client error
httpproxy log (
~/Library/Containers/com.docker.docker/Data/log/host/httpproxy.log)The "successful after" entry appears at the exact moment dockerd reports the broken pipe, with only 536 MB transferred of a 1 GB layer.
dockerd VM log
Shows matching
use of closed network connectionentries forgrpcand api-proxy streams at the same timestamp.Workaround
Add the destination registry to Docker Desktop's Containers Proxy bypass list:
*.ocir.io,phx.ocir.ioAfter this,
httpproxy.logemitscontainer via direct connection because matches container settings excludeand dockerd connects directly to the registry without routing through192.168.65.1:3128. The same 1 GB push completes in ~5 min 20 s on the same machine / network / registry.What's NOT the cause (ruled out during investigation)
I spent several hours narrowing this down; hopefully saves triage time:
docker push(no buildx, no exporter) has the same failure. It's daemon-wide, not buildx-specific.--driver-opt network=host(bypasses gvisor for the container); same failure pattern persisted at the httpproxy layer.net.inet.tcp.ecn_initiate_out=1) — Ruled out:sudo sysctl -w net.inet.tcp.ecn_initiate_out=0did not change the failure.curluploads from the Mac host (bypassing Docker entirely) to Cloudflare complete successfully; SSH uploads to a VM in the same region complete successfully. Only traffic flowing throughdockerd → Docker Desktop httpproxy → destinationfails.Signal for the fix
The bypass workaround confirms the bug is specifically in how
httpproxyhandles long HTTPS CONNECT tunnels when it's in the path. It's not a general networking issue in Docker Desktop — only this specific code path. A likely candidate area is an idle-timer or write-buffer limit in the CONNECT-tunnel handling code that regressed between 4.69.x and 4.70.0.Happy to provide additional diagnostics or test a candidate fix.