← Debugging Guides

阅读中文版本

Docker daemon: TLS certificate error

Fix Docker daemon TLS errors when certificates are expired, the wrong CA is used, or the client and server names mismatch.

intermediatedebuggingdockertlssecurity

Symptoms

  • docker: x509: certificate has expired or is not yet valid
  • Cannot connect to the Docker daemon over TLS
  • It works over a Unix socket but fails over TCP with TLS

Possible causes

  • The daemon or client certificate has expired
  • The client trusts a CA that did not sign the daemon certificate
  • The certificate SAN does not include the hostname used to connect
  • The DOCKER_TLS_VERIFY or DOCKER_CERT_PATH environment is misconfigured

Diagnosis steps

Print the certificate details

openssl x509 -in cert.pem -noout -dates -subject -ext subjectAltName

Interpretation

Expiry and SAN mismatches are visible immediately.

Verify the CA actually signed it

openssl verify -CAfile ca.pem cert.pem

Interpretation

A verification failure means the trust chain is broken.

Check the environment variables for the connection

Interpretation

DOCKER_TLS_VERIFY=1 and DOCKER_CERT_PATH must point at the right cert directory.

Root cause

Docker over TCP with TLS verifies the daemon certificate against the CA supplied to the client and checks the hostname against the SAN. Expired certificates, a mismatched CA, or a SAN that omits the connect hostname all break the handshake, while the Unix socket path bypasses TLS entirely and keeps working.

Fix

Renew expired certificates, ensure the client trusts the CA that signed the daemon certificate, and include every connect hostname or IP in the SAN. Set DOCKER_TLS_VERIFY and DOCKER_CERT_PATH consistently for the client. Only use insecure TCP where the network is fully trusted, and prefer mutual TLS in production.

Verify the fix

Run `docker --tlsverify version` against the daemon; it connects without a certificate error, and openssl verify reports the chain as OK.

Symptoms

The client reports x509: certificate has expired or is not yet valid or a chain verification failure. Local docker over the socket works, so only the TLS path is broken.

Diagnosis

Inspect dates, SANs, and the chain:

openssl x509 -in daemon-cert.pem -noout -dates -ext subjectAltName
openssl verify -CAfile ca.pem daemon-cert.pem
echo "$DOCKER_TLS_VERIFY $DOCKER_CERT_PATH"

Fix

Renew and realign the certificates:

export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=$HOME/.docker/certs
docker --tlsverify version

Regenerate the certificate with the connect hostname in its SAN.

Verification

Connect with --tlsverify; the handshake succeeds, docker version returns both client and server, and openssl verify reports the chain as OK.

Mutual TLS in Production

Remote Docker access should use mutual TLS: the client verifies the daemon, and the daemon verifies the client, so a leaked endpoint alone is not enough to control the host. That requires three certificates — a CA, a server certificate, and a client certificate — all with correct SANs and lifetimes. Rotating them before expiry matters because an expired client certificate produces the same x509 error as a mismatched CA, and the two need different fixes. Automating renewal and distribution avoids the outage that otherwise arrives the day the certificate lapses, often at the least convenient moment.