Docker
Proxy Issues
Image Download
Network Problems
Troubleshooting

Cannot download Docker images behind a proxy

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When Docker cannot pull images behind a corporate proxy, the root cause is usually configuration split across multiple layers. The shell may know about the proxy while the Docker daemon does not, or the proxy may intercept TLS without a trusted certificate installed.

Understand Which Component Is Failing

Image downloads are performed by the Docker daemon, not just by the docker client command you type in a terminal. That distinction matters because exporting HTTP_PROXY in your shell helps subprocesses started from that shell, but it does not automatically configure a background service.

A useful first check is:

bash
docker info

If the daemon is configured correctly, the output often shows proxy settings. If the pull still fails, the error message usually points to one of three categories: authentication, TLS certificate trust, or bypass rules in NO_PROXY.

Configure the Docker Client and Daemon

Start with the usual environment variables for your interactive shell:

bash
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
export NO_PROXY=localhost,127.0.0.1,.example.internal

That is necessary for some tooling around Docker, but for docker pull on Linux you also need the daemon configuration. On systems using systemd, create a drop-in file:

ini
1[Service]
2Environment="HTTP_PROXY=http://proxy.example.com:8080"
3Environment="HTTPS_PROXY=http://proxy.example.com:8080"
4Environment="NO_PROXY=localhost,127.0.0.1,.example.internal"

Save it under /etc/systemd/system/docker.service.d/http-proxy.conf, then reload and restart Docker.

bash
sudo systemctl daemon-reload
sudo systemctl restart docker

Some installations also support proxy settings in daemon.json.

json
1{
2  "proxies": {
3    "default": {
4      "httpProxy": "http://proxy.example.com:8080",
5      "httpsProxy": "http://proxy.example.com:8080",
6      "noProxy": "localhost,127.0.0.1,.example.internal"
7    }
8  }
9}

Use the method documented for your platform and avoid keeping conflicting definitions in several places unless you know which one wins.

Handle Authenticated and Intercepting Proxies

Some proxies require credentials in the proxy URL.

bash
export HTTPS_PROXY=http://username:[email protected]:8080

That works mechanically, but it exposes secrets in shell history and process listings if used carelessly. In managed environments, storing credentials in a protected service configuration is usually safer.

The harder case is TLS interception. If the proxy re-signs certificates, Docker may fail with an x509 trust error even when proxy variables are correct. Then you need the proxy's root certificate installed in the trust store used by Docker. For a private registry, the certificate is often placed under Docker's cert directory for that registry host.

NO_PROXY Is Often the Real Fix

Many failures happen because internal hosts should not go through the proxy at all. Private registries, cluster services, and metadata endpoints frequently need to be listed in NO_PROXY.

A typical internal setup might need values like these:

bash
export NO_PROXY=localhost,127.0.0.1,registry.example.internal,.svc,.cluster.local

If your private registry is routed through the proxy accidentally, pulls may hang, fail authentication, or resolve the wrong certificate chain.

A Reliable Debugging Sequence

Use a short, repeatable workflow instead of changing everything at once.

  1. Confirm the exact error from docker pull.
  2. Check docker info for daemon-level proxy settings.
  3. Verify whether the target registry should be proxied or added to NO_PROXY.
  4. If the error mentions certificates, install the corporate CA in the location Docker uses.
  5. Restart the daemon after configuration changes and test again.

This sequence separates network routing problems from trust problems. Those are different classes of failure and need different fixes.

Common Pitfalls

  • Setting proxy variables only in the shell and assuming the Docker daemon inherits them automatically. Services usually do not.
  • Forgetting to restart Docker after changing daemon or systemd proxy configuration.
  • Omitting internal registries and cluster domains from NO_PROXY, which sends traffic through the wrong path.
  • Ignoring certificate errors when the proxy performs TLS inspection. Proxy settings alone do not solve trust issues.
  • Leaving multiple conflicting proxy definitions in shell files, daemon.json, and service overrides without verifying which one is active.

Summary

  • 'docker pull depends on daemon configuration, not just client-shell variables.'
  • Set HTTP_PROXY, HTTPS_PROXY, and NO_PROXY in the right place for your platform.
  • Use docker info to confirm what the daemon is actually using.
  • Treat TLS interception and missing certificates as a separate problem from proxy routing.
  • Add internal registries to NO_PROXY when they should be reached directly.

Course illustration
Course illustration

All Rights Reserved.