This error occurs when Docker's TLS certificate validation fails due to an expired certificate or incorrect system time. The most common causes are system clock misconfiguration, expired registry certificates, or outdated CA certificates on the Docker host.
The "x509: certificate has expired or is not yet valid" error indicates that Docker cannot establish a secure TLS connection because the certificate's validity period doesn't match the current system time. The x509 standard defines certificate validity through "Not Before" and "Not After" timestamps. This error typically occurs in two scenarios: - **Certificate has expired**: The certificate's "Not After" date has passed. This happens with registry certificates, Let's Encrypt certificates (which expire every 90 days), or Docker client certificates. - **Certificate not yet valid**: The system clock is set to a time before the certificate's "Not Before" date. This commonly occurs in virtual machines, containers, or embedded systems with incorrect time synchronization. Docker validates certificates during: - Pulling images from registries (Docker Hub, private registries) - Pushing images to registries - Docker Swarm manager-worker communication - Docker-machine provisioned hosts - Kubernetes API server connections (when using Docker Desktop) The validation happens at the TLS layer before any Docker operations can proceed, making this a blocking error that must be resolved before continuing.
The most common cause is incorrect system time. Check your system clock first:
# Check current system time and timezone
date
timedatectl
# Check if time is significantly different from actual time
# Compare with: https://time.is/
# If time is wrong, set it manually
sudo date --set="2025-01-15 14:30:00"
# Or sync with NTP server immediately
sudo ntpdate pool.ntp.org
# Or with systemd-timesyncd
sudo timedatectl set-ntp trueFor VMs (Vagrant, VirtualBox, etc.):
# VirtualBox - sync guest time with host
VBoxManage setextradata "VM Name" "VBoxInternal/Devices/VMMDev/0/Config/GetHostTimeDisabled" 0
# Inside the VM, install guest additions and restart
sudo apt-get install virtualbox-guest-utils
sudo systemctl restart vboxadd-serviceAfter fixing time, restart Docker:
sudo systemctl restart dockerEnsure NTP is properly configured to keep time synchronized:
Using systemd-timesyncd (modern systems):
# Enable and start time synchronization
sudo timedatectl set-ntp true
# Check synchronization status
timedatectl status
# View sync details
timedatectl timesync-statusUsing ntpd or chrony:
# Install chrony (recommended for modern systems)
sudo apt-get install chrony # Debian/Ubuntu
sudo yum install chrony # RHEL/CentOS
# Start and enable chrony
sudo systemctl enable chronyd
sudo systemctl start chronyd
# Check sync status
chronyc trackingFor Docker containers, if the container needs accurate time:
# Mount host's localtime (read-only)
docker run -v /etc/localtime:/etc/localtime:ro your-image
# Or set timezone via environment variable
docker run -e TZ=America/New_York your-imageOutdated CA certificates can cause validation failures, especially after the Let's Encrypt DST Root CA X3 expiration in 2021:
Ubuntu/Debian:
# Update CA certificates package
sudo apt-get update
sudo apt-get install --reinstall ca-certificates
# Rebuild certificate store
sudo update-ca-certificates --fresh
# Restart Docker
sudo systemctl restart dockerRHEL/CentOS/Fedora:
# Update CA certificates
sudo yum update ca-certificates
# Or on newer systems
sudo dnf update ca-certificates
# Update trust store
sudo update-ca-trust
# Restart Docker
sudo systemctl restart dockerAlpine (common in Docker images):
# Update CA certificates
apk update && apk add --no-cache ca-certificates
# Update certificate store
update-ca-certificatesIf using docker-machine, client certificates expire after one year by default:
# Check certificate expiration date
openssl x509 -in ~/.docker/machine/certs/cert.pem -text -noout | grep "Not After"
# Regenerate certificates for a specific machine
docker-machine regenerate-certs my-machine
# Regenerate all certificates including CA
docker-machine regenerate-certs --client-certs my-machine
# If the above fails, you may need to recreate the machine
docker-machine rm my-machine
docker-machine create --driver virtualbox my-machineCheck certificate details:
# View all certificate files and their expiration
for cert in ~/.docker/machine/certs/*.pem; do
echo "=== $cert ==="
openssl x509 -in "$cert" -text -noout | grep -E "(Subject:|Not Before|Not After)"
doneDocker Swarm uses certificates for secure node communication that rotate every 90 days by default:
# Check Swarm certificate expiration
docker swarm ca --rotate
# View current Swarm certificates
openssl x509 -in /var/lib/docker/swarm/certificates/swarm-node.crt -text -noout | grep "Not After"
# If certificates are expired, you may need to reinitialize
# WARNING: This will disrupt the cluster
docker swarm leave --force
docker swarm init # On manager node
# Or force rotation with new expiry
docker swarm update --cert-expiry 8760h # 1 yearEnsure all nodes have synchronized time:
# On all Swarm nodes, verify time is in sync
ansible all -m shell -a "date && timedatectl"
# Or manually check each node
docker node ls
# Then SSH to each node and verify timeIf using a private registry, check if its certificate has expired:
# Check registry certificate expiration
echo | openssl s_client -connect your-registry.example.com:443 2>/dev/null | \
openssl x509 -noout -dates
# View detailed certificate info
echo | openssl s_client -showcerts -connect your-registry.example.com:443 2>/dev/null | \
openssl x509 -text -noout | head -30If certificate is expired, renew it:
# For Let's Encrypt certificates (using certbot)
sudo certbot renew
# Generate new self-signed certificate for development
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"
# Update the registry with new certificate and restartAfter renewing, ensure Docker clients have the updated CA certificate:
# Copy new CA to Docker's cert directory
sudo cp new-ca.crt /etc/docker/certs.d/your-registry.example.com/ca.crt
sudo systemctl restart dockerFor Docker Desktop with Kubernetes enabled, expired certificates can prevent the cluster from working:
macOS/Windows - Docker Desktop:
1. Open Docker Desktop
2. Go to Settings/Preferences
3. Navigate to Kubernetes section
4. Click "Reset Kubernetes Cluster"
5. Wait for cluster to reinitialize
Alternative - Reset via command line:
# Delete existing Kubernetes config
rm -rf ~/.kube/config
# In Docker Desktop settings, disable then re-enable Kubernetes
# This regenerates all certificatesIf certificates are still invalid, reset Docker Desktop completely:
1. Docker Desktop > Troubleshoot > Reset to factory defaults
2. Reconfigure Docker Desktop settings
3. Re-enable Kubernetes if needed
Linux with Docker + Kubernetes:
# Check kube-apiserver certificate
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout | grep "Not After"
# Renew certificates with kubeadm
sudo kubeadm certs renew all
sudo systemctl restart kubeletUnderstanding x509 certificate validation:
The x509 standard requires certificates to have validity periods defined by:
- notBefore: Earliest time the certificate is valid
- notAfter: Latest time the certificate is valid
Docker (via Go's crypto/x509 package) checks these against the system clock. Even a few minutes of clock drift can cause validation failures if a certificate just expired or was just issued.
Let's Encrypt DST Root CA X3 expiration (September 30, 2021):
Many older systems stopped trusting Let's Encrypt certificates after this date because they only had the old root CA. The fix is updating CA certificates package or the OS itself.
Systems affected:
- Ubuntu 16.04 and older
- Debian 9 and older
- RHEL/CentOS 7 with outdated packages
- macOS 10.12.0 and older
- Android 7.1.1 and older
Docker-machine certificate lifecycle:
~/.docker/machine/certs/
├── ca.pem # CA certificate (expires in ~3 years)
├── ca-key.pem # CA private key
├── cert.pem # Client certificate (expires in 1 year)
└── key.pem # Client private keyCertificate validation in CI/CD pipelines:
CI runners often use cached images or VMs that may have time drift:
# GitLab CI - add time sync before Docker operations
before_script:
- apt-get update && apt-get install -y ntpdate
- ntpdate pool.ntp.orgDebugging certificate times:
# Check current time vs certificate validity
echo "System time: $(date -u)"
echo "Certificate times:"
openssl x509 -in cert.pem -noout -dates
# Parse and compare dates programmatically
cert_end=$(openssl x509 -in cert.pem -noout -enddate | cut -d= -f2)
cert_epoch=$(date -d "$cert_end" +%s)
now_epoch=$(date +%s)
days_left=$(( (cert_epoch - now_epoch) / 86400 ))
echo "Days until expiration: $days_left"Docker Swarm automatic certificate rotation:
By default, Swarm rotates node certificates every 90 days. This can be adjusted:
# Set certificate expiry to 6 months
docker swarm update --cert-expiry 4320h
# Minimum is 1 hour, maximum is limited by CA certificate validityunable to configure the Docker daemon with file /etc/docker/daemon.json
How to fix 'unable to configure the Docker daemon with file daemon.json' in Docker
docker: Error response from daemon: OCI runtime create failed: container_linux.go: starting container process caused: exec: "/docker-entrypoint.sh": stat /docker-entrypoint.sh: no such file or directory
How to fix 'exec: entrypoint.sh: no such file or directory' in Docker
image operating system "linux" cannot be used on this platform
How to fix 'image operating system linux cannot be used on this platform' in Docker
dockerfile parse error line 5: unknown instruction: RRUN
How to fix 'unknown instruction' Dockerfile parse error in Docker
manifest unknown: manifest unknown
How to fix 'manifest unknown' in Docker