docker pull por VPN: el daemon tiene su propia red
La descarga se ejecuta en el daemon, no en tu shell. Comprueba el contexto, da a ese motor su propia ruta o proxy y luego lee qué intercambio con el registry terminó.
Tu portátil está en la VPN corporativa, curl llega al registry interno y, aun así, docker pull falla con un EOF. Esa combinación no es una contradicción. El comando que escribiste se ejecuta en tu shell, pero la transferencia se ejecuta en el daemon que haya elegido la CLI de Docker, y ese daemon puede estar en un host completamente distinto. Su ruta de red es la que tiene que funcionar, y su configuración de proxy es la que se aplica.
Empieza identificando el motor, no la ruta
Ejecuta docker context show y docker version. La salida de la versión imprime una sección de cliente y una sección de servidor, y el bloque del servidor te dice quién respondió: un motor nativo local, la máquina virtual de Docker Desktop o un daemon en una máquina remota. docker context inspect mostrará el punto final del contexto seleccionado si quieres estar seguro, y ninguno de estos comandos cambia nada.
Una variable de entorno como DOCKER_HOST puede apuntar en silencio la CLI a un motor distinto del que supones, que es la explicación habitual de un portátil que parece estar en la VPN mientras la descarga viaja a otro sitio.
El daemon tiene su propia identidad de red
Un motor remoto necesita su propia ruta aprobada hacia el registry privado. Conectar el cliente VPN de tu portátil da una ruta a ese portátil; no da la misma dirección privada a un daemon que está en un laboratorio o en una subred de nube. Si el motor es Docker Desktop, la descarga ocurre dentro de su máquina virtual, que tiene su propia configuración de red y de proxy, separada del entorno de tu shell.
Por eso un curl correcto en el host es una prueba sobre el host y nada más.
Averigua qué intercambio con el registry terminó
La descarga de una imagen es una secuencia: autenticación, obtención del manifiesto y luego transferencias de blob que a menudo se redirigen a almacenamiento de objetos o a un punto final de CDN. Un docker login correcto solo demuestra el primer paso, y un token puede ser perfectamente válido mientras el host de blob redirigido no es alcanzable desde la red del daemon. Anota la hora exacta, la referencia de la imagen y el primer evento útil del registro del daemon o del cliente antes de cambiar nada.
EOF por sí solo no nombra ninguna causa. Puede ser una conexión truncada, un proxy que soltó el flujo, un tiempo de espera agotado o un problema de MTU, y adivinar entre ellos sin el evento con marca de tiempo es como la gente acaba reconstruyendo un motor sano. Trata el desplazamiento de bytes de la salida del cliente como dato, porque una transferencia que se detiene en el mismo tamaño cada vez es un animal distinto de una que nunca empieza. Registra ambos resultados y compáralos entre intentos.
Configura el componente que transfiere
Para un motor Linux nativo, el proxy va en el entorno del servicio, no en tu shell. Un archivo drop-in en /etc/systemd/system/docker.service.d/ con entradas HTTP_PROXY, HTTPS_PROXY y NO_PROXY, seguido de systemctl daemon-reload y un reinicio, es la disposición documentada. Docker Desktop expone los mismos valores mediante su propia configuración, y editar un perfil de shell no toca ninguno de los dos.
Si se debe llegar al registry directamente por la VPN, el daemon necesita un resolutor, una ruta y una exclusión de proxy deliberada, no solo una exclusión. La coincidencia de NO_PROXY es una comparación de cadenas por componente, y una excepción sin ruta subyacente produce un fallo que parece un problema de proxy.
Cuando la inspección TLS corporativa está en la ruta aprobada, instala su raíz verificada mediante el flujo del motor o de Desktop. Añadir el registry a insecure-registries es un cambio distinto que desactiva la validación, y no es una configuración de almacén de confianza.
Repite una descarga controlada y comprueba qué cambió
Cambia un límite, reinicia el componente que lo posee y repite la misma descarga desde el mismo contexto. Verifica la referencia de imagen y el digest resultantes, no la ausencia de error, porque una capa en caché puede hacer que el segundo intento recorra mucha menos parte de la ruta que el primero. Guarda en el ticket las transferencias que realmente ocurrieron, ya que son el único registro de lo que el reintento probó de verdad.
Los pasos de compilación y los contenedores en ejecución tienen sus propios contextos de red, así que trátalos como preguntas separadas cuando la propia descarga ya funcione.