Docker
Registry
Authentication
Containerization
DevOps

How to know if docker is already logged in to a docker registry server

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

To check whether Docker is logged in to a registry, inspect the ~/.docker/config.json file. If the registry hostname appears under the auths key (or a credsStore / credHelpers entry handles it), Docker has stored credentials for that registry. There is no dedicated docker is-logged-in command, so reading this config file is the standard approach.

bash
cat ~/.docker/config.json

The rest of this article covers how Docker stores credentials across different platforms, how to write reliable login checks for CI/CD pipelines, and how to troubleshoot authentication when things go wrong.

How Docker Stores Credentials

When you run docker login, Docker persists credentials so that subsequent docker push and docker pull commands do not require re-authentication. The storage mechanism depends on your OS and Docker configuration.

Direct Storage in config.json

On systems without a credential helper, Docker stores a base64-encoded username:password string directly in ~/.docker/config.json:

json
1{
2  "auths": {
3    "https://index.docker.io/v1/": {
4      "auth": "dXNlcm5hbWU6cGFzc3dvcmQ="
5    },
6    "registry.example.com": {
7      "auth": "cHJvamVjdDpzZWNyZXQ="
8    }
9  }
10}

Each key under auths is a registry URL. If your target registry appears here with a non-empty auth value, you are logged in.

You can decode the value to verify the username:

bash
echo "dXNlcm5hbWU6cGFzc3dvcmQ=" | base64 --decode
# Output: username:password

Credential Helpers

Modern Docker installations delegate credential storage to the operating system's native keychain. In this case, config.json contains a credsStore key instead of inline credentials:

json
1{
2  "auths": {
3    "https://index.docker.io/v1/": {}
4  },
5  "credsStore": "desktop"
6}
OSCredential HelperStorage Backend
macOSosxkeychainKeychain Access
WindowswincredWindows Credential Manager
Linux (GNOME)secretserviceGNOME Keyring
Linux (headless)passGPG-encrypted pass store
Docker DesktopdesktopDocker Desktop internal store

When a credential helper is configured, the auth field under auths is empty because the actual secret lives in the OS keychain. The presence of the registry key still indicates that Docker has stored credentials for it.

Per-Registry Credential Helpers

You can also configure different helpers for different registries using credHelpers:

json
1{
2  "credHelpers": {
3    "gcr.io": "gcloud",
4    "123456789.dkr.ecr.us-east-1.amazonaws.com": "ecr-login"
5  }
6}

Cloud provider registries (ECR, GCR, ACR) often use their own credential helper binaries that generate short-lived tokens on the fly, so the concept of "logged in" means the helper is configured, not that a static credential is cached.

Checking Login Status Programmatically

Quick Shell Check

To test whether credentials exist for a specific registry in a script:

bash
1#!/bin/bash
2REGISTRY="registry.example.com"
3
4if grep -q "$REGISTRY" ~/.docker/config.json 2>/dev/null; then
5  echo "Credentials found for $REGISTRY"
6else
7  echo "Not logged in to $REGISTRY"
8fi

Using jq for Reliable Parsing

Parsing JSON with grep is fragile. Use jq for accurate checks:

bash
1REGISTRY="https://index.docker.io/v1/"
2
3if jq -e ".auths[\"$REGISTRY\"]" ~/.docker/config.json > /dev/null 2>&1; then
4  echo "Logged in to Docker Hub"
5else
6  echo "Not logged in to Docker Hub"
7fi

The -e flag makes jq return a non-zero exit code if the result is null or false, which makes it usable in conditionals.

Verifying Active Credentials With a Test Pull

Having credentials in config.json does not guarantee they are still valid. Tokens expire, passwords get rotated, and accounts get deactivated. To verify that credentials actually work:

bash
1docker pull registry.example.com/test-image:latest 2>&1
2if [ $? -eq 0 ]; then
3  echo "Credentials are valid"
4else
5  echo "Credentials may be expired or invalid"
6fi

A lighter alternative is to query the registry API directly:

bash
curl -s -o /dev/null -w "%{http_code}" \
  --header "Authorization: Bearer $(docker-credential-desktop get <<< 'https://index.docker.io/v1/')" \
  https://registry-1.docker.io/v2/

A 200 response confirms valid authentication.

Custom Config Path

The default config location is ~/.docker/config.json, but Docker respects the DOCKER_CONFIG environment variable. In CI/CD environments, you may see:

bash
export DOCKER_CONFIG=/path/to/custom/docker-config
cat "$DOCKER_CONFIG/config.json"

Always use ${DOCKER_CONFIG:-$HOME/.docker}/config.json in scripts to handle custom paths:

bash
CONFIG_FILE="${DOCKER_CONFIG:-$HOME/.docker}/config.json"
cat "$CONFIG_FILE"

CI/CD Pipeline Patterns

GitHub Actions

yaml
1- name: Check Docker login
2  run: |
3    if jq -e '.auths["ghcr.io"]' ~/.docker/config.json > /dev/null 2>&1; then
4      echo "Already logged in to GHCR"
5    else
6      echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
7    fi

Login Guard Script

A reusable pattern for any CI system:

bash
1#!/bin/bash
2ensure_docker_login() {
3  local registry="$1"
4  local username="$2"
5  local password="$3"
6  local config="${DOCKER_CONFIG:-$HOME/.docker}/config.json"
7
8  if [ -f "$config" ] && jq -e ".auths[\"$registry\"]" "$config" > /dev/null 2>&1; then
9    echo "Already logged in to $registry"
10  else
11    echo "$password" | docker login "$registry" -u "$username" --password-stdin
12  fi
13}
14
15ensure_docker_login "registry.example.com" "$REGISTRY_USER" "$REGISTRY_PASS"

Logging Out

To remove credentials for a specific registry:

bash
docker logout registry.example.com

To remove all stored credentials:

bash
docker logout

After logging out, the registry entry is removed from (or emptied in) config.json. You can verify by inspecting the file again.

Common Pitfalls

Assuming the auth field in config.json always contains a value is incorrect when a credential helper is configured. The field may be empty or the key may exist with an empty object, while the real credentials live in the OS keychain.

Checking for docker.io instead of https://index.docker.io/v1/ trips up many scripts. Docker Hub uses the full URL as its registry key, not the short hostname. Always verify the exact key format in your config.json.

Using docker login interactively in CI/CD pipelines creates issues because it prompts for input. Always use --password-stdin to pipe the password:

bash
echo "$TOKEN" | docker login registry.example.com -u username --password-stdin

Forgetting that DOCKER_CONFIG can override the default config path means your script checks the wrong file. Always incorporate the environment variable in automated checks.

Storing plaintext credentials in config.json without a credential helper is a security risk on shared machines. Configure a credential helper or use short-lived tokens.

Having expired or rotated credentials in config.json produces confusing "authentication required" errors on push/pull even though the file shows you are "logged in." Validate credentials by actually authenticating, not just checking file contents.

Summary

  • Inspect ~/.docker/config.json and look for your registry under the auths key to determine login status.
  • Account for credential helpers (credsStore, credHelpers) that store secrets in the OS keychain instead of the config file.
  • Use jq for reliable JSON parsing in scripts rather than grep.
  • Respect the DOCKER_CONFIG environment variable for non-default config paths.
  • Having credentials stored does not guarantee they are valid. Test with an actual pull or API call when freshness matters.
  • Use docker logout to cleanly remove stored credentials.

Course illustration
Course illustration

All Rights Reserved.