When running from the command line, to pull from a specific registry I can run these commands:

dockerCommand=$("aws ecr get-login --profile profileName --region us-west-2")
$dockerCommand  (which looks like docker login -u AWS -p ..longPassword.. -e none https://ACCTID.dkr.ecr.us-west-2.amazonaws.com
docker pull ACCTID.dkr.ecr.us-west-2.amazonaws.com/REPO/NAME:TAGNAME

If I want a different registry, I change the region or profileName

Trying this with docker-py, I have

import boto3
import docker
dockerClient = docker.from_env()

session = boto3.setup_default_session(profile_name='vzw')
client = session.client('ecr', region_name='us-west-2')

token = client.get_authorization_token(registryIds=[registryId])

username = 'AWS'
password = token['authorizationData'][0]['authorizationToken']
registry = token['authorizationData'][0]['proxyEndpoint']
regClient = dockerClient.login(username, password, registry)

but the dockerClient refuses the connection with:

bad username or password

From there, once that is working, I'll want to use a docker client pull/push to move the images between registries.

Is the the right direction or should I be trying to implement this entirely with shell scripts? (Python has been especially valuable for the boto calls to describe what is in each registry)


Login Fail

dockerClient refuses the connection with "bad username or password"

The signature of the function you are calling to login is:

def login(self, username, password=None, email=None, registry=None,
          reauth=False, insecure_registry=False, dockercfg_path=None):

Note the position of the registry parameter. It is fourth in the list. So your call of:

regClient = dockerClient.login(username, password, registry)

Is passing your registry as the email since email is the third parameter. Suggest you change to something like:

regClient = dockerClient.login(username, password, registry=registry)

Python or shell?

Is the the right direction or should I be trying to implement this entirely with shell scripts? (Python has been especially valuable for the boto calls to describe what is in each registry)

Go with the Python.

| improve this answer | |
  • 1
    Thank You, that seems to be the problem and at this point it doesn't generate an error. Although the next step seems ambigous now... – efreedom Jun 19 '17 at 5:38
  • The next step seems a little ambiguous regarding the docker pull because the documentation says use dockerClient.images.pull(name, tag=foo). That fails, I presume because I haven't references the regClient or the registry. I have two regClients -- one will be the registry to pull from and the other the registry to push to. – efreedom Jun 19 '17 at 5:47
  • See serverfault.com/a/910728/161394 for a more thorough answer. It gets the correct credentials using boto3 and parses them correctly do perform docker.login. – Malcolm May 21 '19 at 3:53

Complete code example that works:

#!/usr/bin/env python3
import base64, docker, boto3

docker_client = docker.from_env(version='1.24')
ecr_client = boto3.client('ecr', region_name='eu-west-1')

token = ecr_client.get_authorization_token()
username, password = base64.b64decode(token['authorizationData'][0]['authorizationToken']).decode().split(':')
registry = token['authorizationData'][0]['proxyEndpoint']

docker_client.login(username, password, registry=registry)

And of course you should have your AWS credentials set up first, e.g.:

export AWS_ACCESS_KEY_ID=youraccesskey
export AWS_SECRET_ACCESS_KEY=yoursecretaccesskey
| improve this answer | |

I have faced the same problem, you have to:

  1. decode from base64
  2. convert from byte to string
  3. separate the login 'AWS'

    password = (base64.b64decode(response['authorizationData'[0]authorizationToken'])).decode("utf-8").split(":")[-1]
| improve this answer | |

I have found it to be easiest to pass an auth_config with username/password when pushing the image to ECR.

import boto3
import base64
import docker

sess = boto3.Session()
resp = sess.client('ecr').get_authorization_token()
token = resp['authorizationData'][0]['authorizationToken']
token = base64.b64decode(token).decode()
username, password = token.split(':')
auth_config = {'username': username, 'password': password}

# get local docker client
client = docker.from_env()
# build/tag image here....
# then override the docker client config by passing auth_config
client.image.push(<image name>, auth_config=auth_config)

Hope this helps someone!

| improve this answer | |
  • This worked perfect @Martin. Thanks for the solution. – Omkar Kulkarni Mar 4 at 13:45

There's an open issue in the docker-py project about this, and one of their workarounds worked for me - stripping the leading https:// from the registry when performing the Docker login:

registry_url = token['authorizationData'][0]['proxyEndpoint'].replace("https://", "")
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.