How can I tell if I'm logged in to a private Docker registry from a script?

后端 未结 7 1112
粉色の甜心
粉色の甜心 2021-02-04 23:59

How can I tell whether or not I\'m logged in to a private Docker registry server from a script? In other words, has docker login some.registry.com been run success

相关标签:
7条回答
  • 2021-02-05 00:29

    I believe the error message will vary by registry implementation. However, my own technique is to pull an image that doesn't exist and parse any error message:

    $!/bin/sh
    repo="$1"
    msg=$(docker pull ${repo}/missing:missing 2>&1)
    case "$msg" in
      *"requested access to the resource is denied"*|*"pull access denied"*)
        echo "Logged out";;
      *"manifest unknown"*|*"not found"*)
        echo "Logged in, or read access for anonymous allowed";;
      *"Pulling from"*)
        echo "Missing image was not so missing after all?";;
      *) 
        echo "Unknown message: $msg";;
    esac
    

    This has been tested with the docker standalone registry and docker_auth. You'll want to test with registries that you may encounter.

    If your registry server allows anonymous pulls and you want to verify a push is possible, you can create a dummy empty image and replace the pull with a push of that image. E.g.

    #!/bin/sh
    repo=$1
    # note, I do not like the "." here, better to change it to an empty directory
    # see "mktemp" for an option if you cannot make your own empty directory somewhere
    docker build -t "${repo}/empty:test" -f - . <<EODF
    FROM scratch
    EODF
    msg=$(docker push "${repo}/empty:test" 2>&1)
    rc=$?
    if [ "$rc" = "0" ]; then
      echo "Access granted to push"
    else
      case "$msg" in
        *"requested access to the resource is denied"*)
          echo "Access denied";;
        *) 
          echo "Unknown error message: $msg";;
      esac
    fi
    
    0 讨论(0)
  • 2021-02-05 00:34

    This is a little hacky, I think until docker will have a command to check login, there won't be any good solution.
    You can in your bash script try to login with timeout of x seconds, if you aren't logged in the command will try to prompt for username and then it will timeout with status 124. If you are indeed logged in, it will just log you in again using the save credentials and continue with status 0

    #!/bin/bash
    timeout -s SIGKILL 3s docker login some.registry.com >/dev/null 2>&1
    if [ $? -eq 0 ]
    then
       echo Logged In!
    else
       echo Not logged in...
    fi
    
    0 讨论(0)
  • 2021-02-05 00:39

    if docker login worked, you will find a .docker folder on your home directory (~/.docker/), with a config.json file with credentials in it.

    otherwise you would get an error login in.

    Note: docker determine what credentials to use by looking at the registry name:

    if you do

    docker pull myregistry.com/myimage:tag

    docker will look if you're logged in, and if not will check if you have the credentials for the registry myregistry.com and login with those.

    If not you will get a permission error

    0 讨论(0)
  • 2021-02-05 00:45

    When you do the

    Docker login <private registry> -u <user> -p <password> 
    

    command from your terminal, you will have a response: (stored in $?)

    0
    Login Succeeded
    

    if you were successful.

    In your shell script, you could just look at the response you're receiving, if it does not equal 0, you've failed to login.

    sudo docker login <registry> -u <uname> -p <password>
    if [ $? -ne 0 ]; then
        echo Login failed!
    else
        echo Login OK!
    fi
    
    0 讨论(0)
  • 2021-02-05 00:46

    This is a bit hacky, but it works in most of the cases for me:

    if ! grep -q "my.private.registry.com" ~/.docker/config.json ; then
        docker login "my.private.registry.com"
    fi
    

    Basically, you search if there is a record of "my.private.registry.com" in ~/.docker/config.json. However, if the session is expired, this check won't catch it.

    0 讨论(0)
  • 2021-02-05 00:46

    You can parse .docker/config.json and try to manually connect to each registry specified in the file. The file contains the registry address and encoded username and password so you can script this process. You can do that using a library like docker-registry-client.

    pip install docker-registry-client
    

    And then:

    import base64
    import docker_registry_client
    import json
    import os.path
    
    def get_authed_registries():
      result = []
      config_path = os.path.expanduser("~/.docker/config.json")
      if not os.path.isfile(config_path):
        print("No docker config")
        return []
    
      docker_config = json.load(open(config_path))
    
      for registry, auth in docker_config.get("auths", {}).items():
        username, password = base64.b64decode(auth["auth"]).decode("utf-8").split(":", 1)
        if not registry:
          registry = "https://index.docker.io/v1/"
        if not registry.startswith("http"):
          registry = "https://" + registry
        try:
          rc = docker_registry_client.DockerRegistryClient(registry, username=username, password=password)
          result.append(registry)
        except Exception, e:
          print(registry, "failed:", e)
    
      return result
    
    
    get_authed_registries()
    

    A few caveats:

    • This may fail if you're using a credential store.
    • Tested on Python 2.7. Might need small adjustments for Python 3.
    • This code works for authentication, but any further actions on the registry fail. You will need to strip away API version (/v1, /v2, etc.) from the host name for that.
    • The code assumes all registries are HTTPS (unless specified otherwise in config.json)
    • An even more correct version will probably strip away anything but the hostname and try both v1 and v2.

    That said, I was able to get a list of logged-in registries and it correctly ignored expired ECR login.

    0 讨论(0)
提交回复
热议问题