Containers Intermediate

Fixing ‘Docker registry push failed: authentication token expired’ on CentOS Stream / Rocky Linux

Resolve Docker registry push failures caused by expired authentication tokens on CentOS Stream and Rocky Linux systems with this expert guide.

👨‍💻
Senior Systems Architect • Verified in Staging Labs

Resolve Docker registry push failures caused by expired authentication tokens on CentOS Stream and Rocky Linux systems with this expert guide.

When managing Docker containers and images in a production environment, especially on robust server operating systems like CentOS Stream or Rocky Linux, encountering deployment roadblocks can be frustrating. One common issue that halts continuous integration and deployment (CI/CD) pipelines or manual image pushes is the "Docker registry push failed: authentication token expired" error. This guide provides a highly technical, accurate, and step-by-step resolution process for this specific problem, rooted in 16 years of web hosting and DevOps expertise.

Symptom & Error Signature

You will typically observe this error message when attempting to push a Docker image to a remote registry, such as Docker Hub, a private enterprise registry, or a cloud provider's container registry (e.g., AWS ECR, Azure Container Registry, Google Container Registry). The output in your terminal will look similar to one of these variations:

$ docker push myorg/myrepo:latest
The push refers to repository [myorg/myrepo]
An image does not exist locally with the tag: myorg/myrepo
denied: requested access to the resource is denied

or more explicitly:

$ docker push myorg/myrepo:latest
The push refers to repository [myorg/myrepo]
unauthorized: authentication required
Error: Pushing image myorg/myrepo:latest failed: unauthorized: authentication required

The most direct indicator of the problem discussed here is when the error explicitly states:

$ docker push myorg/myrepo:latest
The push refers to repository [myorg/myrepo]
unauthorized: authentication token expired
Error: Pushing image myorg/myrepo:latest failed: unauthorized: authentication token expired

The key phrase authentication token expired immediately points to the underlying issue.

Root Cause Analysis

The "authentication token expired" error signifies that the cached credentials Docker uses to authenticate with a remote registry are no longer valid. When you successfully log in to a Docker registry using the docker login command, Docker generates and stores an authentication token (or a refresh token that can acquire new tokens) in your user's configuration file, typically ~/.docker/config.json. This token grants your Docker client permission to push and pull images from specific registries without requiring you to re-enter your username and password for every subsequent command.

Reasons for Token Expiration:

  1. Time-Based Expiration: For security purposes, all authentication tokens have a limited lifespan. This prevents indefinite access with potentially compromised credentials. Registries enforce varying expiration policies (e.g., hours, days, or weeks) to enhance security posture.
  2. Inactivity: If you haven't interacted with a specific registry for an extended period, its corresponding token in your config.json will naturally expire.
  3. Credential Rotation/Revocation: Your organization might enforce regular rotation of user passwords or API keys. If the underlying credentials used to generate your token are changed or revoked, the token stored on your client becomes invalid.
  4. Security Policy Changes: Registry administrators might update security policies, leading to the invalidation of older token types or forcing a re-authentication.
  5. System Clock Skew (Less Common): While rare, a significant time difference between your client system (CentOS Stream / Rocky Linux) and the registry server can sometimes interfere with token validation. The server might perceive your token as invalid due to a time mismatch, even if it's technically still within its valid period.

Step-by-Step Resolution

The primary and most effective solution to an expired authentication token is to re-authenticate with the Docker registry.

1. Re-authenticate with the Docker Registry

The docker login command is specifically designed to refresh your authentication token and update your ~/.docker/config.json file with new, valid credentials.

  • For Docker Hub (Default Registry): If you are pushing to Docker Hub (the default registry when no explicit URL is provided), simply execute:

    docker login
    

    You will be prompted to enter your Docker Hub username and password.

  • For Private Registries or Cloud Provider Registries: You must specify the full registry URL. Replace <YOUR_REGISTRY_URL> with the actual address of your registry.

    docker login <YOUR_REGISTRY_URL>
    

    Examples:

    • AWS ECR Public: docker login public.ecr.aws
    • AWS ECR Private: docker login <YOUR_AWS_ACCOUNT_ID>.dkr.ecr.<YOUR_AWS_REGION>.amazonaws.com
    • Azure Container Registry: docker login <your-acr-name>.azurecr.io
    • Google Container Registry: docker login gcr.io (or other regional endpoints)
    • Self-Hosted Private Registry: docker login registry.yourcompany.com

    For cloud provider registries like AWS ECR, Azure ACR, or Google GCR, docker login often requires a pre-generated password or specific authentication mechanisms (e.g., via a helper tool or CLI).

    Example for AWS ECR (using AWS CLI):

    # Ensure AWS CLI is installed and configured with appropriate IAM permissions
    aws ecr get-login-password --region <YOUR_AWS_REGION> | docker login --username AWS --password-stdin <YOUR_AWS_ACCOUNT_ID>.dkr.ecr.<YOUR_AWS_REGION>.amazonaws.com
    

    Always consult your cloud provider's official documentation for the most current and accurate authentication steps for their container registries.

    Upon successful login, you should see the message Login Succeeded.

2. Verify System Clock (Optional, for Diagnosis)

While less common, an inaccurate system clock can sometimes cause issues with TLS/SSL certificate validation and token time-based expiry checks, leading to authentication problems.

  • Check your system's current time:

    timedatectl
    

    Ensure that Local time and Universal time are accurate and NTP service is active (or synchronized).

  • Synchronize system time with NTP: If your clock is significantly out of sync, ensure NTP synchronization is enabled and active. On CentOS Stream / Rocky Linux, chronyd is the default NTP client.

    sudo timedatectl set-ntp true
    sudo systemctl restart chronyd
    

3. Clear Existing Docker Credentials (If Re-authentication Fails)

If docker login still fails to resolve the issue, or if you suspect corrupted config.json entries, you can manually remove the problematic cached token.

  • Inspect ~/.docker/config.json: Your Docker client's configuration file, located at ~/.docker/config.json, stores your authentication tokens. You can inspect its contents:

    cat ~/.docker/config.json
    

    Look for an auths section, which contains entries for different registries and their base64-encoded authentication strings.

  • Remove a specific registry entry: To selectively remove credentials for a single, problematic registry, open ~/.docker/config.json with a text editor (e.g., vi, nano) and carefully delete the corresponding JSON block under the auths section.

    {
      "auths": {
        "https://index.docker.io/v1/": {
          "auth": "YOUR_BASE64_ENCODED_AUTH_STRING_FOR_DOCKER_HUB"
        },
        "yourcompany.com/registry": {  <-- This block needs to be removed
          "auth": "ANOTHER_BASE64_ENCODED_AUTH_STRING"
        }
      },
      "credsStore": "desktop"
    }
    

    Exercise extreme caution when manually editing ~/.docker/config.json. Incorrect JSON syntax will render the file unreadable by Docker, potentially causing more issues. It's highly recommended to create a backup before making any changes:

    cp ~/.docker/config.json ~/.docker/config.json.bak
    
  • Remove all Docker credentials (as a last resort): To perform a complete reset of all stored Docker login credentials, you can delete the config.json file. This will effectively log you out of all registries and require re-authentication for any subsequent Docker operations involving remote registries.

    rm ~/.docker/config.json
    

4. Retry the Docker Push

After re-authenticating or clearing and then re-authenticating your credentials, attempt your docker push command again:

docker push myorg/myrepo:latest

The push operation should now complete successfully.

5. Considerations for CI/CD Environments

If this "authentication token expired" error manifests within an automated CI/CD pipeline (e.g., Jenkins, GitLab CI, GitHub Actions, CircleCI), the resolution needs to focus on the pipeline's credential management:

  • Update CI/CD Secrets/Variables: Verify that the Docker registry credentials (username, password, or generated authentication tokens) stored as secrets or environment variables within your CI/CD system are current and have not expired or been rotated.
  • Token Refresh Logic: For registries requiring short-lived tokens, ensure your CI/CD scripts incorporate logic to generate or refresh tokens before attempting a push. For example, AWS ECR tokens are valid for 12 hours.
  • IAM Role/Service Principal Permissions: For cloud provider registries, confirm that the IAM role, service principal, or service account used by your CI/CD runner has the necessary permissions to perform ecr:PutImage, ecr:BatchCheckLayerAvailability, ecr:InitiateLayerUpload, ecr:UploadLayerPart, and ecr:CompleteLayerUpload actions on the target repository.

By systematically following these steps, you can effectively troubleshoot and resolve "Docker registry push failed: authentication token expired" errors on your CentOS Stream or Rocky Linux systems, ensuring smooth and reliable container image deployments.

👨‍💻

Johnathon Wheeler

Senior Systems Architect & DevOps Engineer • Austin, TX

Connect on LinkedIn →

Johnathon has over 16 years of hands-on experience designing, debugging, and scaling Linux web hosting stacks, container clusters, and high-availability database architectures. Every guide on ButItWorkedLocal is independently tested against Debian 12, Ubuntu 24.04/22.04 LTS, Rocky Linux, and Docker environments to guarantee reproducibility in production.

🛡️

Our Production Verification Guarantee

Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.