14

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)

1

5 Answers 5

7

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.

3
  • 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, 2017 at 5:38
  • 1
    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, 2017 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, 2019 at 3:53
23

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
8

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!

1
  • This worked perfect @Martin. Thanks for the solution. Mar 4, 2020 at 13:45
8

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]
    
0

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://", "")

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .