The 'Client.Timeout exceeded' error occurs when Docker cannot complete a connection to a registry (Docker Hub, private registry, or self-hosted) within the default timeout period. This is typically caused by network connectivity issues, proxy misconfigurations, DNS problems, firewall restrictions, or the registry being unreachable.
The error message "Error response from daemon: Get https://myregistry:5000/v2/: net/http: request canceled (Client.Timeout exceeded)" indicates that Docker's HTTP client initiated a request to a container registry but did not receive a response within the allowed time limit. The request was automatically canceled after the timeout threshold was reached. This error can occur when connecting to any container registry, including: - Docker Hub (registry-1.docker.io) - Private registries (your own registry at a custom domain:port) - GitHub Container Registry (ghcr.io) - Amazon ECR, Google Container Registry, Azure Container Registry The timeout mechanism is a safety feature that prevents Docker commands from hanging indefinitely. However, when triggered unexpectedly, it usually points to one of these underlying issues: 1. **Network path issues**: The request never reaches the registry server due to firewall rules, routing problems, or the registry being down. 2. **Slow connections**: On low-bandwidth connections, large operations may exceed the timeout before completing. 3. **Proxy misconfiguration**: Corporate proxies that aren't properly configured for Docker traffic. 4. **DNS resolution failures**: The registry hostname cannot be resolved to an IP address. 5. **TLS/SSL handshake problems**: Certificate issues that cause the connection to stall. Unlike a "connection refused" error where the server actively rejects the connection, a timeout error means the connection attempt simply took too long with no response at all.
First, check if the registry is reachable from your host machine (outside of Docker):
# For a private registry
curl -v https://myregistry:5000/v2/
# For Docker Hub
curl -v https://registry-1.docker.io/v2/
# Test DNS resolution
nslookup myregistry
# or
dig myregistry
# Test network connectivity
ping myregistry
telnet myregistry 5000If curl works but Docker fails, the issue is likely Docker-specific configuration (proxy, DNS, or certificates). If curl also fails, the issue is at the network level.
Ensure your firewall allows outbound connections to the registry:
# Check if port is open (Linux)
sudo iptables -L -n | grep 5000
# For Docker Hub, ensure port 443 is open
sudo iptables -L -n | grep 443
# Test connection with nc (netcat)
nc -zv myregistry 5000
# On macOS, check Application Firewall
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstateCommon ports to allow:
- Port 443: Docker Hub, ghcr.io, and most cloud registries
- Port 5000: Default port for self-hosted Docker Registry
- Port 5001: Often used for registry authentication
If behind a corporate firewall, contact your IT team to whitelist the registry domain and port.
If you're behind a corporate proxy, Docker needs explicit configuration:
Linux (systemd):
# Create drop-in directory
sudo mkdir -p /etc/systemd/system/docker.service.d
# Create proxy configuration
sudo nano /etc/systemd/system/docker.service.d/http-proxy.confAdd your proxy settings:
[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,myregistry,.company.internal"Reload and restart Docker:
sudo systemctl daemon-reload
sudo systemctl restart dockerDocker Desktop (Windows/Mac):
Go to Settings > Resources > Proxies and configure your proxy settings there.
Verify proxy is applied:
sudo systemctl show --property=Environment dockerDNS issues are a common cause of registry timeouts. Configure Docker to use reliable DNS servers:
# Edit Docker daemon configuration
sudo nano /etc/docker/daemon.jsonAdd DNS configuration:
{
"dns": ["8.8.8.8", "8.8.4.4", "1.1.1.1"]
}Restart Docker:
sudo systemctl restart dockerFor private registries, ensure the hostname is resolvable:
# Add to /etc/hosts if needed
echo "192.168.1.100 myregistry" | sudo tee -a /etc/hostsFor Docker Desktop: Go to Settings > Docker Engine and add the DNS configuration to the JSON editor.
If your private registry uses a self-signed certificate, Docker won't trust it by default. You have two options:
Option 1: Add certificate to Docker's trust store (recommended)
# Create certificate directory
sudo mkdir -p /etc/docker/certs.d/myregistry:5000
# Copy the registry's CA certificate
sudo cp ca.crt /etc/docker/certs.d/myregistry:5000/ca.crt
# Restart Docker
sudo systemctl restart dockerOption 2: Configure as insecure registry (not recommended for production)
sudo nano /etc/docker/daemon.jsonAdd:
{
"insecure-registries": ["myregistry:5000"]
}sudo systemctl restart dockerNote: Using insecure registries exposes you to man-in-the-middle attacks. Only use this for testing or isolated networks.
IPv6 can cause DNS resolution delays on some networks:
# Check if IPv6 is causing issues
curl -4 -v https://myregistry:5000/v2/ # Force IPv4
curl -6 -v https://myregistry:5000/v2/ # Force IPv6 (may fail)If IPv4 works but IPv6 fails, disable IPv6:
# Add to /etc/sysctl.conf
sudo nano /etc/sysctl.confAdd:
net.ipv6.conf.all.disable_ipv6=1
net.ipv6.conf.default.disable_ipv6=1
net.ipv6.conf.lo.disable_ipv6=1Apply and restart Docker:
sudo sysctl --system
sudo systemctl restart dockerVPNs often interfere with Docker registry connections:
1. Test without VPN: Temporarily disconnect your VPN and try the Docker command again.
2. If it works without VPN, configure split tunneling to exclude registry traffic:
Most VPN clients allow you to exclude specific domains or IP ranges. Add these to your VPN's split tunnel configuration:
- Your private registry domain (myregistry)
- Docker Hub: registry-1.docker.io, auth.docker.io, production.cloudflare.docker.com
3. Alternative: Use VPN's internal DNS if your registry is inside the VPN network:
# Configure Docker to use VPN's DNS
sudo nano /etc/docker/daemon.json{
"dns": ["10.0.0.1"] // Your VPN's DNS server
}On slow or unstable connections, reduce the number of parallel operations:
sudo nano /etc/docker/daemon.jsonAdd:
{
"max-concurrent-downloads": 1,
"max-concurrent-uploads": 1
}sudo systemctl restart dockerThis reduces bandwidth usage per operation, making each individual request less likely to timeout. The default values are 3 for downloads and 5 for uploads.
For very slow connections, you can also try pulling during off-peak hours when network congestion is lower.
If the issue is intermittent, retry with additional debugging information:
# Enable Docker daemon debug mode
sudo nano /etc/docker/daemon.jsonAdd:
{
"debug": true
}sudo systemctl restart docker
# Watch Docker logs while running your command
sudo journalctl -u docker -f &
# Try your command
docker pull myregistry:5000/myimage:latestFor transient issues, implement retry logic:
# Retry script
for i in {1..5}; do
docker pull myregistry:5000/myimage:latest && break
echo "Attempt $i failed, waiting 10 seconds..."
sleep 10
doneDon't forget to disable debug mode after troubleshooting:
{
"debug": false
}### Understanding Docker's Timeout Behavior
Docker uses Go's net/http client for registry communication. The default timeout is typically 30 seconds for most operations. When this error occurs, it means:
1. The TCP connection was established (or attempted)
2. The HTTP request was sent
3. No response headers were received within the timeout period
The full error pattern is:
Error response from daemon: Get "https://myregistry:5000/v2/": net/http: request canceled (Client.Timeout exceeded while awaiting headers)### WSL2 and Windows-Specific Issues
When using Docker Desktop with WSL2:
- Docker runs inside a WSL2 VM, which has its own network stack
- Hosts file entries must be in the Windows hosts file (C:\Windows\System32\drivers\etc\hosts), not WSL's /etc/hosts
- DNS resolution uses the Windows DNS client
Windows network adapter issues:
1. Open Network Connections (ncpa.cpl)
2. Find "vEthernet (WSL)" or "vEthernet (DockerNAT)"
3. Right-click > Properties > IPv4 > Properties
4. Set DNS to 8.8.8.8 and 8.8.4.4
### Private Registry Best Practices
For self-hosted registries, ensure:
1. Proper TLS configuration: Use certificates from a trusted CA or properly distribute your CA certificate to all Docker clients.
2. Health checks: Configure load balancers with appropriate health check endpoints (/v2/ returns 200 OK for healthy registries).
3. Timeout tuning on registry side: If your registry is under heavy load, increase its own timeout settings:
# Registry config.yml
http:
addr: :5000
net: tcp
relativeurls: false
draintimeout: 60s4. Dedicated network: Place the registry on a stable, low-latency network path.
### CI/CD Pipeline Considerations
In CI/CD environments (GitHub Actions, GitLab CI, Jenkins), this error often indicates:
- Rate limiting: Too many unauthenticated pulls
- Shared infrastructure: Other jobs consuming bandwidth
- Ephemeral networking: CI runners with inconsistent network paths
Solutions:
1. Authenticate to increase limits: docker login in your pipeline
2. Use a pull-through cache: Configure a local registry as a mirror
3. Cache base images: Pre-pull images in your CI environment
4. Add retry logic: Wrap Docker commands in retry scripts
### Alternative Diagnosis with Docker Events
Monitor Docker events during a timeout:
# In one terminal, start event monitoring
docker events --filter 'type=image'
# In another terminal, attempt the pull
docker pull myregistry:5000/myimage:latestThis can reveal if Docker is making progress or stuck at a particular stage.
image operating system "linux" cannot be used on this platform
How to fix 'image operating system linux cannot be used on this platform' in Docker
manifest unknown: manifest unknown
How to fix 'manifest unknown' in Docker
cannot open '/etc/passwd': Permission denied
How to fix 'cannot open: Permission denied' in Docker
Error response from daemon: failed to create the ipvlan port
How to fix 'failed to create the ipvlan port' in Docker
toomanyrequests: Rate exceeded for anonymous users
How to fix 'Rate exceeded for anonymous users' in Docker Hub