Solved: Docker SSL Handshake Failed Error with Private Registry
Quick Fix Summary
TL;DRAdd your registry's CA certificate to Docker's trusted certificates at /etc/docker/certs.d/<registry_host>/ca.crt and restart Docker.
Docker cannot establish a secure TLS connection to your private registry because it doesn't trust the registry's SSL/TLS certificate. This typically occurs when using self-signed certificates or certificates from a private Certificate Authority.
Diagnosis & Causes
Recovery Steps
Step 1: Verify the SSL Connection Manually
First, confirm the SSL issue exists and examine the certificate details using OpenSSL.
openssl s_client -connect your.registry.com:443 -showcerts
openssl s_client -connect your.registry.com:443 2>&1 | openssl x509 -noout -dates -subject -issuer Step 2: Place the CA Certificate in Docker's Trust Directory
Copy the registry's CA certificate (or the self-signed certificate itself) to the correct Docker directory. Create the directory if it doesn't exist.
sudo mkdir -p /etc/docker/certs.d/your.registry.com
sudo cp your-ca-certificate.crt /etc/docker/certs.d/your.registry.com/ca.crt Step 3: Restart the Docker Daemon
Restart Docker to pick up the new trusted certificates. Use the appropriate command for your init system.
sudo systemctl restart docker
sudo service docker restart Step 4: Test the Fix
Verify the SSL handshake now succeeds by attempting to log in or pull an image.
docker login your.registry.com
docker pull your.registry.com/myimage:latest Step 5: Alternative - Insecure Registry (TEMPORARY FIX ONLY)
For emergency recovery only, configure Docker to treat the registry as insecure. WARNING: This disables SSL verification.
sudo nano /etc/docker/daemon.json Step 5 (continued): Add Insecure Registry Configuration
Add the 'insecure-registries' key to the daemon.json file, then restart Docker.
{
"insecure-registries": ["your.registry.com"]
} Architect's Pro Tip
"For Kubernetes clusters pulling from private registries, you must also add the CA certificate to the nodes at the OS level (/etc/ssl/certs/) and update the containerd or Docker configuration there."
Frequently Asked Questions
Do I need to restart Docker after adding a certificate?
Yes, the Docker daemon only reads the certificate trust store on startup. A restart is required for it to recognize new certificates.
What if my registry uses a different port, like 5000?
Include the port in the directory name: /etc/docker/certs.d/your.registry.com:5000/ca.crt.
How do I get the CA certificate from my registry?
If you control the registry, use the certificate file from its TLS configuration. Otherwise, extract it using `openssl s_client -connect host:port 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > cert.crt`.