Your laptop is on the corporate VPN, curl reaches the internal registry, and docker pull still dies with an EOF. That combination is not a contradiction. The command you typed runs in your shell, but the transfer runs in whichever daemon the Docker CLI has selected, and that daemon may be on another host entirely. Its network path is the one that has to work, and its proxy settings are the ones that apply.

Start by identifying the engine, not the route

Run docker context show and docker version. The version output prints a client section and a server section, and the server block tells you what answered: a local native engine, the Docker Desktop virtual machine, or a daemon on a remote machine. docker context inspect will show the endpoint of the selected context if you want to be certain, and none of these commands change anything.

An environment variable such as DOCKER_HOST can silently point the CLI at a different engine than the one you assume, which is the usual explanation for a laptop that appears to be on the VPN while the pull travels somewhere else.

The daemon has its own network identity

A remote engine needs its own approved path to the private registry. Connecting your laptop's VPN client gives that laptop a route; it does not give a daemon sitting in a lab or a cloud subnet the same private address. If the engine is Docker Desktop, the pull happens inside its virtual machine, which has its own networking and proxy configuration that is separate from your shell's environment.

That is why a successful curl on the host is evidence about the host and nothing more.

Find which registry exchange ended

An image pull is a sequence: authentication, manifest retrieval, then blob transfers that often redirect to object storage or a CDN endpoint. A successful docker login proves the first step only, and a token can be perfectly valid while the redirected blob host is unreachable from the daemon's network. Note the exact time, the image reference and the first useful event from the daemon or client log before you change anything.

EOF on its own names no cause. It can be a truncated connection, a proxy that dropped the stream, a timeout, or an MTU problem, and guessing between them without the timestamped event is how people end up rebuilding a healthy engine. Treat the byte offset in the client output as data, because a transfer that stops at the same size every time is a different animal from one that never starts. Record both outcomes and compare them across attempts.

Configure the component that transfers

For a native Linux engine, the proxy belongs in the service environment, not in your shell. A drop-in file under /etc/systemd/system/docker.service.d/ with HTTP_PROXY, HTTPS_PROXY and NO_PROXY entries, followed by systemctl daemon-reload and a restart, is the documented arrangement. Docker Desktop exposes the same values through its own settings, and editing a shell profile does not touch either of them.

If the registry should be reached directly over the VPN, the daemon needs a resolver, a route and a deliberate proxy exclusion rather than an exclusion alone. NO_PROXY matching is a per-component string comparison, and an exemption with no underlying route produces a failure that looks like a proxy problem.

When enterprise TLS inspection sits in the approved path, install its verified root through the engine or Desktop workflow. Adding the registry to insecure-registries is a different change that disables validation, and it is not a trust-store configuration.

Repeat one controlled pull and check what changed

Change one boundary, restart the component that owns it, and repeat the same pull from the same context. Verify the resulting image reference and digest rather than the absence of an error, because a cached layer can make a second attempt exercise far less of the path than the first one did. Keep the transfers that actually occurred in the ticket, since they are the only record of what the retry really tested.

Build steps and running containers have their own network contexts, so treat them as separate questions once the pull itself works.

مۇناسىۋەتلىك ماقالىلەر