How to fix Error response from daemon: Get https://registry-1.docker.io/v2/: Proxy Authentication Required in Docker

DockerINTERMEDIATEMEDIUMUpdated May 28, 2026· 290 views

Docker returns HTTP 407 "Proxy Authentication Required" when pulling images through a corporate proxy that needs credentials. Fix it by configuring authenticated proxy settings for the Docker daemon.

Quick fix

Fixes 407

# Create the override directory
sudo mkdir -p /etc/systemd/system/docker.service.d

# Create the proxy configuration file
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf > /dev/null << 'EOF'
[Service]
Environment="HTTP_PROXY=http://username:password@proxy.example.com:8080"
Environment="HTTPS_PROXY=http://username:password@proxy.example.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,.example.com"
EOF
  1. Configure the proxy for the Docker daemon via a systemd drop-in (Linux)
  2. Configure the proxy in daemon.json (Docker Engine 23.0+)
  3. URL-encode special characters in the proxy password
  4. Set both HTTP_PROXY and HTTPS_PROXY
docker — error
# Create the override directory
sudo mkdir -p /etc/systemd/system/docker.service.d
# Create the proxy configuration file
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf > /dev/null << 'EOF'
[Service]
Environment="HTTP_PROXY=http://username:password@proxy.example.com:8080"
Environment="HTTPS_PROXY=http://username:password@proxy.example.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,.example.com"
EOF
Error response from daemon: Get https://registry-1.docker.io/v2/: Proxy Authentication Required

What this error means

The "Proxy Authentication Required" error (HTTP 407) means the Docker daemon is behind a proxy server that requires authentication, and valid proxy credentials are either missing, incorrect, or not configured where the daemon can read them. When you run `docker pull`, `docker login`, or `docker build`, the daemon connects to a container registry such as registry-1.docker.io. If outbound traffic is routed through an authenticated proxy, the proxy returns 407 and refuses to forward the request until it receives valid credentials. This is common in corporate environments where all outbound traffic must traverse a proxy, often backed by Active Directory/LDAP. The key detail that trips people up is that the Docker daemon does not read your shell's `HTTP_PROXY`/`HTTPS_PROXY` environment variables — it has its own proxy configuration (a systemd drop-in, or the `proxies` block in `daemon.json` on Docker 23.0+) that must be set separately and then loaded with a daemon restart.

Typical symptoms

  • Docker pull commands fail with '407 Proxy Authentication Required'
  • Unable to pull any images from Docker Hub or other registries
  • docker login fails with proxy authentication errors
  • docker build fails when trying to download base images
  • Error message contains 'Get "https://registry-1.docker.io/v2/"'
  • Docker commands work off the corporate network but fail when connected to it or the VPN
  • The same error occurs across all registries (Docker Hub, gcr.io, quay.io)

Common causes

  1. The Docker daemon has no proxy configured — it does not inherit your shell's HTTP_PROXY/HTTPS_PROXY variables and needs its own systemd drop-in or daemon.json setting
  2. Proxy credentials (username/password) are missing from the daemon's proxy configuration
  3. HTTPS_PROXY is not set, so requests to https:// registry URLs are not proxied (Docker's Go runtime selects the proxy variable by URL scheme)
  4. The proxy password contains special characters that must be URL-encoded inside the proxy URL
  5. Proxy settings exist in the system or shell environment but were never added to the Docker daemon service, so the daemon never sees them
  6. Proxy credentials have expired or were changed
  7. The corporate proxy uses NTLM/Kerberos authentication, which Docker cannot perform directly and needs a local bridge (e.g. Cntlm)
  8. Conflicting proxy values are defined in more than one place (systemd drop-in and daemon.json), and the wrong one wins

How to fix "Error response from daemon: Get https://registry-1.docker.io/v2/: Proxy Authentication Required"

1Configure the proxy for the Docker daemon via a systemd drop-in (Linux)

The Docker daemon does not read your shell environment. On systemd-based Linux, give it a drop-in override:

bash
# Create the override directory
sudo mkdir -p /etc/systemd/system/docker.service.d

# Create the proxy configuration file
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf > /dev/null << 'EOF'
[Service]
Environment="HTTP_PROXY=http://username:password@proxy.example.com:8080"
Environment="HTTPS_PROXY=http://username:password@proxy.example.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,.example.com"
EOF

Replace username, password, proxy.example.com, and 8080 with your real values.

Secure the file — it contains credentials in plaintext:

bash
sudo chmod 600 /etc/systemd/system/docker.service.d/http-proxy.conf
sudo chown root:root /etc/systemd/system/docker.service.d/http-proxy.conf

Reload systemd and restart Docker:

bash
sudo systemctl daemon-reload
sudo systemctl restart docker

Verify the variables were applied:

bash
sudo systemctl show --property=Environment docker

If possible, prefer a dedicated proxy service account over your personal credentials, since the secret is stored on disk.

2Configure the proxy in daemon.json (Docker Engine 23.0+)

Docker Engine 23.0 and later support a proxies block in the daemon configuration file, which is often cleaner than a systemd drop-in:

bash
sudo tee /etc/docker/daemon.json > /dev/null << 'EOF'
{
  "proxies": {
    "http-proxy": "http://username:password@proxy.example.com:8080",
    "https-proxy": "http://username:password@proxy.example.com:8080",
    "no-proxy": "localhost,127.0.0.1,.example.com"
  }
}
EOF

Restrict permissions, since the password is stored in cleartext:

bash
sudo chmod 600 /etc/docker/daemon.json
sudo chown root:root /etc/docker/daemon.json

Restart Docker to apply:

bash
sudo systemctl restart docker

Avoid defining the proxy in both `daemon.json` and a systemd drop-in at the same time — pick one source of truth to prevent confusing precedence conflicts. If you switch to daemon.json, remove the systemd http-proxy.conf file.

3URL-encode special characters in the proxy password

If the proxy password contains characters that are significant inside a URL, encode them or the daemon will parse the proxy URL incorrectly. Common encodings:

| Character | URL Encoded |
|-----------|-------------|
| @ | %40 |
| # | %23 |
| $ | %24 |
| % | %25 |
| & | %26 |
| ! | %21 |
| ? | %3F |
| = | %3D |
| : | %3A |
| space | %20 |

Example: the password P@ss#word! becomes P%40ss%23word%21:

bash
Environment="HTTPS_PROXY=http://username:P%40ss%23word%21@proxy.example.com:8080"

Note that you must URL-encode the value even when using EnvironmentFile= or daemon.json, because the proxy URL is parsed as a URL in every case. If you use an environment file, secure it the same way:

bash
sudo tee /etc/docker/proxy.env > /dev/null << 'EOF'
HTTP_PROXY=http://username:P%40ss%23word%21@proxy.example.com:8080
HTTPS_PROXY=http://username:P%40ss%23word%21@proxy.example.com:8080
NO_PROXY=localhost,127.0.0.1,.example.com
EOF
sudo chmod 600 /etc/docker/proxy.env
sudo chown root:root /etc/docker/proxy.env

sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf > /dev/null << 'EOF'
[Service]
EnvironmentFile=/etc/docker/proxy.env
EOF

sudo systemctl daemon-reload
sudo systemctl restart docker
4Set both HTTP_PROXY and HTTPS_PROXY

Docker's Go-based runtime chooses the proxy variable based on the request's URL scheme. Registry traffic to https://registry-1.docker.io/v2/ is selected by HTTPS_PROXY, so if only HTTP_PROXY is set, HTTPS registry requests are sent directly (or unproxied) and fail. Always set both:

bash
Environment="HTTP_PROXY=http://username:password@proxy.example.com:8080"
Environment="HTTPS_PROXY=http://username:password@proxy.example.com:8080"

The proxy URL itself normally uses the http:// scheme even for HTTPS_PROXY: the client opens an HTTP CONNECT tunnel to the proxy and the end-to-end TLS to the registry is then tunneled through it. Use an https:// proxy scheme only if your proxy explicitly terminates TLS on its listener.

Confirm both variables are present on the daemon:

bash
sudo systemctl show --property=Environment docker | tr ' ' '\n' | grep -i proxy
5Configure the proxy in Docker Desktop (Windows/macOS)

On Docker Desktop the daemon runs inside a managed VM, so configure the proxy through the app rather than editing host systemd files:

1. Open Docker Desktop and click the gear icon (Settings).
2. Go to Resources > Proxies.
3. Enable Manual proxy configuration.
4. Enter the proxy URLs (including credentials if required):
- Web Server (HTTP): http://username:password@proxy.example.com:8080
- Secure Web Server (HTTPS): http://username:password@proxy.example.com:8080
- Bypass: localhost,127.0.0.1
5. Click Apply & Restart.

Note: the proxies block in ~/.docker/config.json configures proxies that are injected into containers at build/run time, not the daemon's own registry connection. For the daemon's proxy on Docker Desktop, use the Settings UI above.

6Bridge NTLM/Kerberos proxies with Cntlm

If the corporate proxy requires NTLM, NTLMv2, or Kerberos/Negotiate authentication (common with Microsoft proxies), Docker cannot authenticate directly. Run a local proxy bridge such as Cntlm that handles the NTLM handshake and exposes an unauthenticated local endpoint:

bash
# Install Cntlm
sudo apt-get install cntlm   # Debian/Ubuntu
sudo dnf install cntlm       # RHEL/Fedora

Generate a password hash so the cleartext password does not have to live in the config:

bash
cntlm -H -u username -d DOMAIN

Put the generated PassNTLMv2 hash into /etc/cntlm.conf (do not store the plaintext Password line in production):

ini
Username    your_username
Domain      YOUR_DOMAIN
PassNTLMv2  <hash-from-cntlm-H>

Proxy       corporate-proxy.example.com:8080
NoProxy     localhost, 127.0.0.*, 10.*, .example.com

Listen      127.0.0.1:3128

Secure and start it:

bash
sudo chmod 600 /etc/cntlm.conf
sudo systemctl enable --now cntlm

Then point the Docker daemon at the local, credential-free bridge (no secrets in the Docker config):

bash
Environment="HTTP_PROXY=http://127.0.0.1:3128"
Environment="HTTPS_PROXY=http://127.0.0.1:3128"
7Verify the proxy configuration

Confirm the daemon picked up the proxy and can reach a registry:

bash
# Docker reports its configured proxies near the bottom of the output
docker info

# Pull a small image end to end
docker pull hello-world

If it still fails, raise the daemon log level via daemon.json (do not run a second dockerd by hand while the service is running):

json
{
  "debug": true
}

Then restart and follow the logs:

bash
sudo systemctl restart docker
sudo journalctl -u docker.service -f

You can also reproduce the request outside Docker to isolate the proxy from the daemon:

bash
https_proxy='http://username:password@proxy.example.com:8080' \
  curl -sv https://registry-1.docker.io/v2/

A 200 or 401 Unauthorized (registry auth, not 407) from this curl confirms the proxy itself is accepting your credentials.

8Clear stale Docker Hub credentials if login is the problem

If docker login itself reports proxy/auth problems after the proxy is correctly configured, refresh the stored registry credentials. Prefer docker logout over deleting your config file, because ~/.docker/config.json also holds your proxy and credential-store settings:

bash
# Remove cached Docker Hub auth token only
docker logout

# Log back in once the proxy is working
docker login

If you suspect a corrupt credential helper, inspect (do not blindly delete) the config:

bash
grep -E 'credsStore|credHelpers' ~/.docker/config.json

Only if the file is genuinely corrupt, back it up before removing it so you can restore your proxy block:

bash
cp ~/.docker/config.json ~/.docker/config.json.bak

Advanced notes

Proxy configuration precedence

If a proxy is defined in more than one place, the effective value can be surprising. Keep a single source of truth. In practice: daemon.json proxies and the systemd drop-in both configure the daemon — do not set both. The daemon also does not read your interactive shell's exported variables, which is the most common reason "it works in my terminal but Docker still 407s."

Daemon proxy vs. container proxy

These are two independent settings:
- Daemon proxy (this article): used by the daemon to pull/push images. Set via systemd drop-in or daemon.json proxies.
- Container proxy: injected into containers for apt-get, npm, etc. Set via the proxies block in ~/.docker/config.json or per-run with docker run -e HTTPS_PROXY=....

SSL/TLS-inspecting proxies

Many corporate proxies perform TLS interception (they re-sign traffic with an internal CA). This causes x509 certificate errors *in addition to* 407 auth errors. The correct, secure fix is to install the corporate root CA so the daemon trusts the re-signed certificates:

bash
sudo cp corporate-ca.crt /usr/local/share/ca-certificates/corporate-ca.crt
sudo update-ca-certificates
sudo systemctl restart docker

On RHEL/Fedora, place the CA in /etc/pki/ca-trust/source/anchors/ and run sudo update-ca-trust.

Do not add "insecure-registries": ["registry-1.docker.io"] to work around this. That flag disables TLS verification for the registry, leaves the daemon open to man-in-the-middle attacks on your image pulls, and does not actually solve an SSL-inspection certificate problem — installing the corporate CA is the only correct fix. Reserve insecure-registries for a private registry you fully control on a trusted network, never for Docker Hub.

PAC files

Docker does not evaluate Proxy Auto-Config (PAC) files. If your organization uses one, read the PAC to determine the concrete proxy host:port for registry hosts and configure Docker with that direct value.

Air-gapped or proxy-hostile environments

If proxy configuration is impractical, run an internal registry mirror or pull-through cache and point Docker at it via a registry-mirrors entry in daemon.json, so day-to-day pulls never traverse the corporate proxy at all.

Frequently asked questions

What does "407" mean?
The "Proxy Authentication Required" error (HTTP 407) means the Docker daemon is behind a proxy server that requires authentication, and valid proxy credentials are either missing, incorrect, or not configured where the daemon can read them. io. If outbound traffic is routed through an authenticated proxy, the proxy returns 407 and refuses to forward the request until it receives valid credentials.
How do I fix "407"?
Docker returns HTTP 407 "Proxy Authentication Required" when pulling images through a corporate proxy that needs credentials. Fix it by configuring authenticated proxy settings for the Docker daemon.
What causes "407"?
The Docker daemon has no proxy configured — it does not inherit your shell's HTTP_PROXY/HTTPS_PROXY variables and needs its own systemd drop-in or daemon.json setting Proxy credentials (username/password) are missing from the daemon's proxy configuration HTTPS_PROXY is not set, so requests to https:// registry URLs are not proxied (Docker's Go runtime selects the proxy variable by URL scheme)
Is the "407" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading