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