This error occurs when Docker cannot verify the SSL/TLS certificate of a registry or server. It typically happens with private registries using self-signed certificates, corporate proxies that intercept HTTPS traffic, or when the CA certificate is not installed on the Docker host.
The "x509: certificate signed by unknown authority" error appears when Docker's TLS verification fails because it cannot find a trusted Certificate Authority (CA) that signed the certificate presented by the registry or server. Docker relies on secure HTTPS connections to verify the authenticity and integrity of container images. This commonly happens in several scenarios: - **Private registries** using self-signed certificates that aren't in Docker's trust store - **Corporate environments** where proxy servers intercept HTTPS traffic and re-sign certificates with their own CA - **Air-gapped environments** where internal CAs are used for security compliance - **Misconfigured certificate chains** where intermediate certificates are missing The x509 package in Go (which Docker uses) validates certificates against the system's CA certificate store and Docker's own certificate directory. When neither contains the signing CA, Docker refuses the connection to prevent potential man-in-the-middle attacks.
The most direct fix is to place the CA certificate in Docker's certificate directory. This tells Docker to trust certificates signed by that CA for the specific registry:
# Create the directory for your registry (include port if not 443)
sudo mkdir -p /etc/docker/certs.d/your-registry.example.com:5000
# Copy your CA certificate (must be named ca.crt)
sudo cp your-ca-certificate.crt /etc/docker/certs.d/your-registry.example.com:5000/ca.crt
# Restart Docker to apply changes
sudo systemctl restart dockerThe directory name must match exactly how you reference the registry in your Docker commands:
- Registry at myregistry.com on port 443: /etc/docker/certs.d/myregistry.com/ca.crt
- Registry at myregistry.com:5000: /etc/docker/certs.d/myregistry.com:5000/ca.crt
Adding the certificate to your operating system's CA store makes it trusted system-wide, including by Docker:
Ubuntu/Debian:
# Copy certificate to system CA directory
sudo cp your-ca-certificate.crt /usr/local/share/ca-certificates/
# Update CA certificates
sudo update-ca-certificates
# Restart Docker
sudo systemctl restart dockerRHEL/CentOS/Fedora:
# Copy certificate to CA trust directory
sudo cp your-ca-certificate.crt /etc/pki/ca-trust/source/anchors/
# Update CA trust
sudo update-ca-trust
# Restart Docker
sudo systemctl restart dockerOpenSUSE:
# Copy certificate
sudo cp your-ca-certificate.crt /etc/pki/trust/anchors/
# Update certificates
sudo update-ca-certificates
# Restart Docker
sudo systemctl restart dockerIf you don't have the CA certificate file, you can extract it directly from the registry:
# Extract certificate from the registry
openssl s_client -showcerts -connect your-registry.example.com:443 </dev/null 2>/dev/null | \
openssl x509 -outform PEM > registry-cert.crt
# View certificate details to verify
openssl x509 -in registry-cert.crt -text -noout | head -20
# For registries with multiple certificates in the chain,
# save all of them (intermediate + root)
openssl s_client -showcerts -connect your-registry.example.com:443 </dev/null 2>/dev/null | \
awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/{ print }' > full-chain.crtAfter extracting, place the certificate in Docker's certs.d directory or the system CA store as shown in previous steps.
For development or testing environments where certificate management isn't critical, you can configure Docker to skip TLS verification for specific registries:
# Edit or create Docker daemon configuration
sudo nano /etc/docker/daemon.jsonAdd your registry to the insecure-registries list:
{
"insecure-registries": ["your-registry.example.com:5000"]
}Then restart Docker:
sudo systemctl restart dockerWarning: This disables TLS verification entirely for the specified registry. Never use this in production as it makes you vulnerable to man-in-the-middle attacks. Only use for:
- Local development registries
- Temporary testing scenarios
- Isolated networks with no external access
In corporate environments, security appliances often intercept HTTPS traffic and re-sign certificates. You need to install the corporate root CA certificate:
1. Obtain your corporate CA certificate - Contact your IT department or security team
2. For Docker on Linux:
# Add corporate CA to system store
sudo cp corporate-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
sudo systemctl restart docker3. For Docker Desktop on Windows:
- Export the corporate CA from Windows Certificate Manager
- Open Docker Desktop Settings > Docker Engine
- Or place certificate in %USERPROFILE%\.docker\certs.d\<registry>
4. For Docker Desktop on macOS:
- Add certificate to Keychain Access
- Mark it as "Always Trust"
- Restart Docker Desktop
5. Verify proxy is the issue:
# Check if proxy is intercepting certificates
curl -v https://registry-1.docker.io 2>&1 | grep -i "issuer"
# If issuer is your company name instead of DigiCert/Amazon/etc., proxy is interceptingDocker caches certificate information, so you must restart the Docker daemon after any certificate changes:
# Linux with systemd
sudo systemctl restart docker
# Linux with SysVinit
sudo service docker restart
# Verify Docker is running
docker info
# Test registry connection
docker pull your-registry.example.com:5000/test-imageDocker Desktop (Windows/macOS):
1. Right-click Docker icon in system tray
2. Select "Restart"
3. Or quit and reopen Docker Desktop
If the error persists after restart, verify the certificate is in the correct location:
# Check Docker's certificate directory
ls -la /etc/docker/certs.d/
# Check system CA certificates were updated
ls -la /etc/ssl/certs/ | grep your-cert-nameCertificate locations Go/Docker checks:
Docker (via Go) checks certificates in these locations:
- /etc/docker/certs.d/<registry>/ca.crt - Registry-specific
- /etc/ssl/certs/ca-certificates.crt (Debian/Ubuntu)
- /etc/pki/tls/certs/ca-bundle.crt (RHEL/CentOS)
- /etc/ssl/ca-bundle.pem (OpenSUSE)
Using client certificates:
If your registry requires client certificate authentication, place all three files in the certs.d directory:
/etc/docker/certs.d/your-registry.example.com/
├── ca.crt # CA certificate
├── client.cert # Client certificate
└── client.key # Client private keyKubernetes/containerd:
For Kubernetes clusters using containerd (v1.19+), configure certificates in containerd's config:
# /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.configs."your-registry.example.com".tls]
ca_file = "/etc/containerd/certs.d/your-registry.example.com/ca.crt"Self-signed certificate generation:
For development registries, generate a proper self-signed certificate:
# Generate CA and registry certificate
openssl req -newkey rsa:4096 -nodes -sha256 \
-keyout registry.key -x509 -days 365 \
-out registry.crt -subj "/CN=your-registry.example.com" \
-addext "subjectAltName=DNS:your-registry.example.com,IP:192.168.1.100"Debugging certificate chains:
# View full certificate chain
openssl s_client -showcerts -connect registry.example.com:443 </dev/null
# Verify certificate against specific CA
openssl verify -CAfile ca.crt registry.crtimage 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