Skip to content
DevOps AI ToolKit
Newsletter
All guides
Docker with AI By James Joyner IV · · 8 min read

Docker Error Guide: 'unexpected EOF' on Image Pull — Fix Broken Layer Downloads

Quick answer

Fix Docker 'unexpected EOF' during pull: repair truncated layer downloads from network drops, proxy/MTU issues, registry timeouts, and corrupt cache, then pull large images reliably.

Part of the Docker Build & Image Errors hub
  • #docker
  • #troubleshooting
  • #errors
  • #registry
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

unexpected EOF during docker pull means the connection carrying a layer closed before Docker received all the bytes it expected. The download stream ended mid-transfer, so the layer cannot be verified or extracted. It is almost always a transport problem — a dropped connection, a proxy cutting the stream, an MTU mismatch, or a registry timeout — rather than a bad image.

The literal error appears while pulling or extracting a layer:

docker pull myregistry.example.com/app:latest
...
a1b2c3d4e5f6: Downloading [==============>    ]  312.4MB/512MB
failed to register layer: unexpected EOF

A close variant surfaces from the daemon as:

Error response from daemon: unexpected EOF

Symptoms

  • Pulls of large images fail partway, often at the same approximate percentage each time.
  • Small images pull fine; only big layers fail — a classic sign of an MTU or timeout ceiling.
  • Retrying sometimes succeeds, sometimes fails at a different point (flaky network/proxy).
  • The failure follows a corporate proxy, VPN, or firewall in the path.
  • journalctl -u docker shows repeated unexpected EOF or net/http: request canceled.

Common Root Causes

  • Network instability — Wi-Fi drops, VPN flaps, or a saturated link interrupting a long-running layer download.
  • Proxy or firewall cutting the stream — an inspecting proxy that buffers or times out large responses and closes the connection early.
  • MTU mismatch — an oversized MTU (common with VPN/overlay networks) blackholes large packets, so big layers stall and the connection dies.
  • Registry-side timeout or rate limiting — the registry closes idle or slow connections, or throttles the client mid-transfer.
  • Corrupt local download cache — a partially written layer in /var/lib/docker that the daemon keeps trying to reuse.
  • Insufficient concurrency limits under load — many parallel layer pulls overwhelming a constrained link.

Diagnostic Workflow

Confirm it is transport, not the image, by retrying and watching where it breaks:

docker pull --disable-content-trust myregistry.example.com/app:latest
journalctl -u docker --since '5 min ago' | grep -i 'eof\|canceled\|timeout\|tls'

Test raw connectivity and payload transfer to the registry, bypassing Docker:

curl -v -o /dev/null https://registry-1.docker.io/v2/
time curl -sS -o /dev/null https://<registry>/v2/<repo>/blobs/<digest>

Check for an MTU problem — large packets failing while small ones pass:

ping -M do -s 1472 registry-1.docker.io      # 1472+28=1500; try 1400 if this fails
ip link show docker0 | grep mtu

Inspect proxy configuration the daemon is using:

systemctl show --property=Environment docker | tr ' ' '\n' | grep -i proxy
cat /etc/systemd/system/docker.service.d/http-proxy.conf 2>/dev/null

Example Root Cause Analysis

A CI runner behind a corporate VPN failed to pull a 1.8 GB ML image, dying near 60% every time with failed to register layer: unexpected EOF. Small images pulled fine. ping -M do -s 1472 failed but -s 1372 succeeded — a classic MTU blackhole introduced by the VPN tunnel, which had an effective MTU below 1500.

The fix was to lower Docker’s MTU to match the tunnel by setting "mtu": 1400 in /etc/docker/daemon.json and restarting the daemon. With packets sized to fit the path, the large layers transferred intact and the pull completed. As a belt-and-suspenders measure, the team also added a pull retry with backoff in the pipeline to absorb transient VPN flaps.

Prevention Best Practices

  • Match MTU to the path. On VPN/overlay/cloud networks, set Docker’s mtu in daemon.json to the tunnel’s real MTU to avoid large-packet blackholes.
  • Retry pulls with backoff in CI so a single transient EOF does not fail the whole job.
  • Use a pull-through registry mirror close to your builders to shorten and stabilize the download path.
  • Exempt registries from stream-inspecting proxies, or ensure the proxy supports large, long-lived responses.
  • Prune corrupt partial layers if a specific pull keeps failing at the same point (docker system prune then re-pull).
  • Keep images lean so individual layers are smaller and less likely to be interrupted.

Quick Command Reference

docker pull <image>                              # reproduce
journalctl -u docker | grep -i eof               # daemon-side detail
ping -M do -s 1472 <registry-host>               # MTU probe (drop to 1400)
ip link show docker0 | grep mtu                  # current bridge MTU
curl -v -o /dev/null https://<registry>/v2/      # raw reachability
docker system prune                              # clear corrupt partials
# /etc/docker/daemon.json -> { "mtu": 1400 } then: systemctl restart docker

Conclusion

unexpected EOF on pull is a broken download, not a broken image: the byte stream ended early. Prove it is transport by testing raw connectivity and probing MTU, then fix the path — right-size MTU for VPN/overlay networks, exempt the registry from stream-cutting proxies, and add pull retries. A nearby registry mirror makes large pulls dramatically more reliable. See also the net/http request canceled guide and the full Docker guides.

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.