CRITICAL

Solved: Docker SSL Handshake Failed with GCP Artifact Registry

Quick Fix Summary

TL;DR

Run `gcloud auth configure-docker` and restart Docker daemon to refresh GCP credentials and TLS certificates.

Docker cannot establish a secure TLS connection to GCP Artifact Registry due to expired, missing, or misconfigured SSL certificates. This blocks all container image operations, halting deployments and CI/CD pipelines.

Diagnosis & Causes

  • Expired or missing gcloud application default credentials.
  • Docker daemon not configured to use gcloud as a credential helper.
  • System clock skew causing certificate validation failure.
  • Corporate firewall or proxy intercepting TLS traffic.
  • Outdated CA certificates in the Docker host OS.
  • Recovery Steps

    1

    Step 1: Reconfigure Docker with gcloud Credential Helper

    Force gcloud to reconfigure Docker's authentication mechanism for all relevant GCP regions, ensuring the credential helper is properly registered.

    bash
    gcloud auth configure-docker us-central1-docker.pkg.dev us-east1-docker.pkg.dev us-west1-docker.pkg.dev
    sudo systemctl restart docker
    2

    Step 2: Manually Authenticate and Verify Credentials

    Generate fresh GCP access tokens and explicitly log Docker into the Artifact Registry, bypassing any cached stale credentials.

    bash
    gcloud auth login
    gcloud auth print-access-token | docker login -u oauth2accesstoken --password-stdin https://us-central1-docker.pkg.dev
    3

    Step 3: Update System CA Certificates

    Install the latest CA certificate bundle on the host and explicitly copy it into the Docker container's trust store to resolve unknown certificate authority errors.

    bash
    sudo apt-get update && \
      sudo apt-get install -y ca-certificates
    sudo cp /etc/ssl/certs/ca-certificates.crt /usr/local/share/ca-certificates/&&sudo update-ca-certificates
    4

    Step 4: Diagnose with Direct curl and openssl

    Use openssl to inspect the registry's certificate chain and curl to test authentication independently of Docker, isolating the network layer.

    bash
    openssl s_client -showcerts -connect us-central1-docker.pkg.dev:443 < /dev/null 2>/dev/null | openssl x509 -text
    curl -v -H "Authorization: Bearer $(gcloud auth print-access-token)" https://us-central1-docker.pkg.dev/v2/
    5

    Step 5: Configure Docker Daemon for Insecure Registry (LAST RESORT)

    As a temporary last resort for critical recovery, configure the Docker daemon to treat the specific Artifact Registry as insecure. WARNING: Disables TLS verification.

    bash
    sudo tee /etc/docker/daemon.json << EOF
    {"insecure-registries": ["us-central1-docker.pkg.dev"]}
    EOF
    sudo systemctl daemon-reload
    sudo systemctl restart docker

    Architect's Pro Tip

    "The gcloud credential helper caches tokens in ~/.docker/config.json. If Step 1 fails, delete this file and rerun `gcloud auth configure-docker` to force a clean rebuild."

    Frequently Asked Questions

    I ran `gcloud auth configure-docker` but still get the error. What's next?

    Check your Docker daemon logs (`journalctl -u docker`) for specifics. The issue is often a mismatch between the project in `gcloud config set project` and the image you're pulling.

    Does this affect Kubernetes pulling images from GAR?

    Yes. Kubernetes nodes need the same host-level certificate and gcloud authentication setup, or must use a Workload Identity service account for secure, token-less access.

    How can I prevent this in CI/CD pipelines?

    Use short-lived service account keys or Workload Identity. Avoid long-lived user credentials. Pre-pull base images to worker nodes and implement image cache layers.

    Related Docker Guides