How to fix x509: certificate is valid for *.docker.io, not myregistry.com in Docker

DockerINTERMEDIATEMEDIUMUpdated Dec 6, 2025ยท 225 views

This error occurs when Docker attempts to connect to a registry or server, but the SSL/TLS certificate presented does not match the hostname being accessed. The certificate's Common Name (CN) or Subject Alternative Names (SANs) do not include the domain you're trying to reach.

Quick fix

Fixes x509

# Check the certificate from the registry
openssl s_client -connect myregistry.com:443 -servername myregistry.com </dev/null 2>/dev/null | \
  openssl x509 -noout -text | grep -A1 "Subject:"

# Check the Subject Alternative Names
openssl s_client -connect myregistry.com:443 -servername myregistry.com </dev/null 2>/dev/null | \
  openssl x509 -noout -text | grep -A1 "Subject Alternative Name"

# Full certificate details
openssl s_client -showcerts -connect myregistry.com:443 </dev/null 2>&1 | head -50
  1. Verify the certificate being presented
  2. Check for proxy/firewall interception
  3. Verify DNS resolution
  4. Regenerate Docker Machine certificates
docker โ€” error
# Check the certificate from the registry
openssl s_client -connect myregistry.com:443 -servername myregistry.com </dev/null 2>/dev/null | \
openssl x509 -noout -text | grep -A1 "Subject:"
# Check the Subject Alternative Names
openssl s_client -connect myregistry.com:443 -servername myregistry.com </dev/null 2>/dev/null | \
openssl x509 -noout -text | grep -A1 "Subject Alternative Name"
# Full certificate details
openssl s_client -showcerts -connect myregistry.com:443 </dev/null 2>&1 | head -50
x509: certificate is valid for *.docker.io, not myregistry.com

What this error means

The "x509: certificate is valid for X, not Y" error is a TLS certificate validation failure that occurs when there's a mismatch between the hostname Docker is connecting to and the hostnames listed in the server's certificate. Every TLS certificate contains a list of valid hostnames in two fields: - **Common Name (CN):** The primary hostname the certificate was issued for - **Subject Alternative Names (SANs):** Additional hostnames the certificate covers (wildcards like `*.docker.io` are common) When Docker connects to a registry (e.g., `myregistry.com`), it checks whether that hostname appears in the certificate's CN or SAN list. If Docker finds `*.docker.io` in the certificate but is trying to connect to `myregistry.com`, verification fails because the certificate was issued for a completely different domain. This error typically indicates one of several situations: - **Network/proxy interception:** A corporate proxy or firewall is intercepting HTTPS traffic and presenting its own certificate - **DNS misconfiguration:** Your DNS is resolving the registry hostname to the wrong IP address - **Docker Machine IP changes:** After a reboot, docker-machine may get a new IP that doesn't match the certificate - **Wrong certificate installed:** The registry server has the wrong certificate configured

Typical symptoms

  • docker pull fails with 'x509: certificate is valid for X, not Y'
  • docker login to private registry returns hostname mismatch error
  • Error message shows certificate is valid for a different domain than expected
  • The error occurs after changing network settings or rebooting
  • Docker commands fail only on certain networks (e.g., corporate VPN)
  • Error contains unexpected hostnames like *.dropbox.com or company internal names
  • docker-machine commands fail with IP address mismatch errors

Common causes

  1. Corporate proxy/firewall intercepting HTTPS traffic and presenting its own certificate
  2. DNS resolving the registry hostname to the wrong server IP address
  3. Docker Machine IP address changed after reboot (common with Hyper-V/VirtualBox)
  4. Registry server misconfigured with certificate for wrong domain
  5. Certificate doesn't include all required Subject Alternative Names
  6. Network routing issue directing traffic to wrong server
  7. VPN or network configuration causing traffic to be routed incorrectly

How to fix "x509: certificate is valid for *.docker.io, not myregistry.com"

1Verify the certificate being presented

First, check what certificate the server is actually presenting to understand the mismatch:

bash
# Check the certificate from the registry
openssl s_client -connect myregistry.com:443 -servername myregistry.com </dev/null 2>/dev/null | \
  openssl x509 -noout -text | grep -A1 "Subject:"

# Check the Subject Alternative Names
openssl s_client -connect myregistry.com:443 -servername myregistry.com </dev/null 2>/dev/null | \
  openssl x509 -noout -text | grep -A1 "Subject Alternative Name"

# Full certificate details
openssl s_client -showcerts -connect myregistry.com:443 </dev/null 2>&1 | head -50

If the certificate shows unexpected hostnames (like your company's proxy hostname, *.dropbox.com, or a completely different domain), this indicates network interception or misconfiguration.

2Check for proxy/firewall interception

Corporate networks often intercept HTTPS traffic for security scanning. If you see unexpected certificate issuers, a proxy is likely involved:

bash
# Check who issued the certificate
openssl s_client -connect registry-1.docker.io:443 </dev/null 2>/dev/null | \
  openssl x509 -noout -issuer

# Expected: issuer=C = US, O = DigiCert Inc, ...
# If intercepted: issuer=CN = YourCompany Security Proxy, ...

If proxy interception is detected:

1. Contact your IT department for the corporate root CA certificate
2. Install the corporate CA certificate:

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

# RHEL/CentOS
sudo cp corporate-ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust
sudo systemctl restart docker

3. Or configure Docker Desktop to use the corporate certificate via Settings

3Verify DNS resolution

Ensure the registry hostname resolves to the correct IP address:

bash
# Check DNS resolution
nslookup myregistry.com
dig myregistry.com

# Compare with expected IP from registry documentation
# or ping from a known-working machine

# Check /etc/hosts for any overrides
cat /etc/hosts | grep myregistry

# Test direct connection to the IP
curl -v https://<expected-ip>/ -H "Host: myregistry.com"

If DNS is returning the wrong IP:
- Check your /etc/hosts file for incorrect entries
- Verify DNS server configuration in /etc/resolv.conf
- Try using a different DNS server temporarily:

bash
# Test with Google DNS
nslookup myregistry.com 8.8.8.8
4Regenerate Docker Machine certificates

If you're using Docker Machine and the IP address changed (common after rebooting), regenerate the certificates:

bash
# List your Docker machines
docker-machine ls

# Check the current IP vs certificate IP
docker-machine ip default
docker-machine inspect default | grep -A5 "AuthOptions"

# Regenerate certificates for the machine
docker-machine regenerate-certs default

# Note: This will restart Docker and may stop running containers
# Confirm when prompted

# Verify the connection works
docker-machine env default
eval $(docker-machine env default)
docker info

For Hyper-V users, you may need to set a static IP to prevent this recurring:
- Open Hyper-V Manager
- Configure your Docker VM's network adapter with a static IP
- Regenerate certificates after the IP change

5Fix registry certificate configuration

If you control the registry, ensure the certificate includes all required hostnames:

bash
# Generate a new certificate with proper SANs
openssl req -newkey rsa:4096 -nodes -sha256 \
  -keyout registry.key -x509 -days 365 \
  -out registry.crt \
  -subj "/CN=myregistry.com" \
  -addext "subjectAltName=DNS:myregistry.com,DNS:*.myregistry.com,IP:192.168.1.100"

For Docker Registry v2:
Update your registry configuration to use the new certificate:

yaml
# config.yml
version: 0.1
storage:
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  tls:
    certificate: /certs/registry.crt
    key: /certs/registry.key

Then restart your registry:

bash
docker restart registry
6Configure insecure registry (development only)

As a temporary workaround for development environments only, you can skip TLS verification:

bash
# Edit Docker daemon configuration
sudo nano /etc/docker/daemon.json

Add the registry to the insecure list:

json
{
  "insecure-registries": ["myregistry.com:5000"]
}

Restart Docker:

bash
sudo systemctl restart docker

WARNING: This completely disables TLS verification for this registry:
- Never use in production
- Vulnerable to man-in-the-middle attacks
- Only suitable for isolated development networks
- Better to fix the certificate properly

7Verify and test the fix

After applying any fix, verify the connection works:

bash
# Test TLS connection
openssl s_client -connect myregistry.com:443 -servername myregistry.com </dev/null

# Verify certificate matches hostname
openssl s_client -connect myregistry.com:443 </dev/null 2>/dev/null | \
  openssl x509 -noout -subject -issuer

# Test Docker login
docker login myregistry.com

# Test pulling an image
docker pull myregistry.com/test-image:latest

# Check Docker daemon logs if issues persist
sudo journalctl -u docker.service -f

Advanced notes

Understanding certificate hostname validation:
TLS certificates use two fields for hostname validation:
- CN (Common Name): Legacy field, limited to one hostname
- SAN (Subject Alternative Name): Modern standard, supports multiple hostnames and wildcards

Modern browsers and Docker prefer SAN over CN. A certificate with only CN may fail validation in some configurations.

Wildcard certificate limitations:
Wildcard certificates (*.example.com) only match one subdomain level:
- *.example.com matches registry.example.com
- *.example.com does NOT match dev.registry.example.com
- For multi-level subdomains, use explicit SANs

Docker Machine certificate storage:
Docker Machine stores certificates in:

bash
~/.docker/machine/machines/<machine-name>/
โ”œโ”€โ”€ ca.pem
โ”œโ”€โ”€ cert.pem
โ”œโ”€โ”€ key.pem
โ”œโ”€โ”€ server.pem
โ””โ”€โ”€ server-key.pem

SNI (Server Name Indication):
When multiple registries share an IP (common with CDNs), the client must send the hostname via SNI. Verify SNI is working:

bash
openssl s_client -connect registry-1.docker.io:443 -servername registry-1.docker.io

Debugging in Kubernetes/containerd:
For containerd-based setups, check certificate configuration:

bash
# View containerd registry config
cat /etc/containerd/config.toml | grep -A10 "registry.configs"

# Test with crictl
crictl pull myregistry.com/image:tag

Common interception scenarios:
1. Zscaler/corporate security: Contact IT for the Zscaler root CA
2. Charles Proxy/Fiddler: Disable SSL proxying for Docker traffic
3. Antivirus software: Some AV programs intercept HTTPS - check settings

Frequently asked questions

What does "x509" mean?
The "x509: certificate is valid for X, not Y" error is a TLS certificate validation failure that occurs when there's a mismatch between the hostname Docker is connecting to and the hostnames listed in the server's certificate. com), it checks whether that hostname appears in the certificate's CN or SAN list. com, verification fails because the certificate was issued for a completely different domain.
How do I fix "x509"?
This error occurs when Docker attempts to connect to a registry or server, but the SSL/TLS certificate presented does not match the hostname being accessed. The certificate's Common Name (CN) or Subject Alternative Names (SANs) do not include the domain you're trying to reach.
What causes "x509"?
Corporate proxy/firewall intercepting HTTPS traffic and presenting its own certificate DNS resolving the registry hostname to the wrong server IP address Docker Machine IP address changed after reboot (common with Hyper-V/VirtualBox)
Is the "x509" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading