How to connect to AWS ECR using python docker-py

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)

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

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]
    

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!

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.

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

This is the answer you’re looking for: How to connect to AWS ECR using python docker-py - Server Fault