How to Authenticate and Connect to AWS ECR Using Python Docker SDK


10 views

Working with Amazon Elastic Container Registry (ECR) through Python's docker-py SDK presents unique authentication challenges compared to the AWS CLI approach. The traditional method using aws ecr get-login doesn't directly translate to Python implementations.

Here's what happens under the hood when authenticating with ECR:

1. AWS generates a temporary authorization token
2. This token is Base64 encoded (username:password format)
3. The token contains AWS credentials with limited lifetime
4. Docker client uses these credentials to authenticate

Here's the corrected approach using boto3 and docker-py:

import base64
import boto3
import docker

def get_ecr_client(profile_name='default', region_name='us-west-2'):
    """Initialize AWS ECR client with specified profile and region"""
    session = boto3.Session(profile_name=profile_name)
    return session.client('ecr', region_name=region_name)

def authenticate_to_ecr(docker_client, ecr_client, registry_id=None):
    """Authenticate Docker client with AWS ECR"""
    auth_data = ecr_client.get_authorization_token(
        registryIds=[registry_id] if registry_id else []
    ).get('authorizationData', [])[0]
    
    token = base64.b64decode(auth_data['authorizationToken']).decode()
    username, password = token.split(':')
    registry_url = auth_data['proxyEndpoint']
    
    return docker_client.login(
        username=username,
        password=password,
        registry=registry_url,
        reauth=True
    )

# Usage example:
docker_client = docker.from_env()
ecr_client = get_ecr_client(profile_name='vzw', region_name='us-west-2')
auth_response = authenticate_to_ecr(docker_client, ecr_client, '123456789012')

print(f"Authentication successful: {auth_response}")

1. Incorrect Token Decoding: The authorization token needs proper Base64 decoding before use.

2. Registry URL Format: Ensure the registry URL doesn't include the 'https://' prefix when passing to docker-py.

3. Profile Configuration: Verify your AWS credentials profile exists in ~/.aws/credentials.

For moving images between registries, you'll need to authenticate to both:

def transfer_image(source_client, dest_client, image_name):
    """Transfer image between ECR registries"""
    # Authenticate to both registries
    source_auth = authenticate_to_ecr(docker_client, source_client)
    dest_auth = authenticate_to_ecr(docker_client, dest_client)
    
    # Pull from source
    docker_client.images.pull(image_name)
    
    # Tag for destination
    dest_image = image_name.replace(
        source_client.meta.region_name,
        dest_client.meta.region_name
    )
    docker_client.images.get(image_name).tag(dest_image)
    
    # Push to destination
    return docker_client.images.push(dest_image)

For production environments, consider:

  • Caching authorization tokens (they're valid for 12 hours)
  • Using multi-threading for bulk operations
  • Implementing retry logic for failed authentication attempts

When working with AWS Elastic Container Registry (ECR) programmatically, authentication is handled differently than with standard Docker registries. The AWS CLI provides a convenient get-login command that generates temporary credentials, but when using Python's docker-py library, we need to handle this process differently.

First, ensure you have the required Python packages installed:

pip install boto3 docker

Here's the proper way to authenticate with ECR using docker-py:

import boto3
import docker
import base64

# Initialize Docker client
docker_client = docker.from_env()

# Configure AWS session
session = boto3.Session(profile_name='your_profile', region_name='us-west-2')
ecr_client = session.client('ecr')

# Get ECR authorization token
response = ecr_client.get_authorization_token()
auth_data = response['authorizationData'][0]
token = auth_data['authorizationToken']
endpoint = auth_data['proxyEndpoint']

# Decode the token and extract credentials
username, password = base64.b64decode(token).decode('utf-8').split(':')

# Login to ECR
login_response = docker_client.login(
    username=username,
    password=password,
    registry=endpoint,
    reauth=True
)

print(f"Successfully logged in to {endpoint}")

The most frequent issues occur with:

  • Incorrect AWS credentials or permissions
  • Mismatched regions between boto3 client and ECR repository
  • Expired tokens (ECR tokens are only valid for 12 hours)

Once authenticated, you can perform standard Docker operations:

# Pull an image
image = docker_client.images.pull('123456789012.dkr.ecr.us-west-2.amazonaws.com/my-repo:latest')

# Push an image
push_logs = docker_client.images.push('123456789012.dkr.ecr.us-west-2.amazonaws.com/my-repo:latest')

For working with multiple ECR registries across different AWS accounts or regions:

def get_ecr_client(profile_name, region_name):
    session = boto3.Session(profile_name=profile_name, region_name=region_name)
    return session.client('ecr')

def authenticate_to_ecr(docker_client, ecr_client):
    response = ecr_client.get_authorization_token()
    auth_data = response['authorizationData'][0]
    token = auth_data['authorizationToken']
    endpoint = auth_data['proxyEndpoint']
    username, password = base64.b64decode(token).decode('utf-8').split(':')
    return docker_client.login(username=username, password=password, registry=endpoint)

Always:

  • Store AWS credentials securely (using AWS Secrets Manager or environment variables)
  • Rotate credentials regularly
  • Implement proper IAM policies with least privilege
  • Never hardcode credentials in your scripts