ECR
AWS ECR
Fully managed Docker container registry
Amazon Elastic Container Registry (ECR) is a fully managed Docker container registry for storing, managing, and deploying container images.
Key Features
| Feature | Description |
|---|---|
| Private Registries | Secure storage for container images |
| Public Registries | Share images publicly |
| Vulnerability Scanning | Detect security issues |
| Lifecycle Policies | Automated image cleanup |
| Replication | Cross-region and cross-account |
| Immutable Tags | Prevent tag overwrites |
Repository Types
| Type | Access | Use Case |
|---|---|---|
| Private | AWS account only | Production images |
| Public | Anyone | Open source projects |
Registry URL Format
{aws_account_id}.dkr.ecr.{region}.amazonaws.com/{repository_name}:{tag}Example:
123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:v1.0.0Getting Started
Create Repository
aws ecr create-repository \
--repository-name my-app \
--image-scanning-configuration scanOnPush=true \
--image-tag-mutability IMMUTABLEAuthenticate Docker
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin \
123456789012.dkr.ecr.us-east-1.amazonaws.comPush Image
# Build image
docker build -t my-app:latest .
# Tag for ECR
docker tag my-app:latest \
123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest
# Push
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latestPull Image
docker pull 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latestImage Tags
Tagging Strategy
| Strategy | Example | Use Case |
|---|---|---|
| Semantic versioning | v1.2.3 | Releases |
| Git SHA | abc1234 | CI/CD |
| Build number | build-123 | Automation |
| Environment | prod, staging | Deployment |
| Date | 2024-01-15 | Daily builds |
Tag Multiple
docker tag my-app:latest \
123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:v1.0.0
docker tag my-app:latest \
123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:$(git rev-parse --short HEAD)
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app --all-tagsImage Scanning
Types of Scanning
| Type | Description |
|---|---|
| Basic | CVE database scan |
| Enhanced | Amazon Inspector integration |
Enable Scanning
# On push
aws ecr create-repository \
--repository-name my-app \
--image-scanning-configuration scanOnPush=true
# Manual scan
aws ecr start-image-scan \
--repository-name my-app \
--image-id imageTag=latestGet Scan Results
aws ecr describe-image-scan-findings \
--repository-name my-app \
--image-id imageTag=latestEnhanced Scanning
# Enable for registry
aws ecr put-registry-scanning-configuration \
--scan-type ENHANCED \
--rules '[
{
"scanFrequency": "CONTINUOUS_SCAN",
"repositoryFilters": [{"filter": "*", "filterType": "WILDCARD"}]
}
]'Lifecycle Policies
Automatically clean up old images:
Policy Examples
{
"rules": [
{
"rulePriority": 1,
"description": "Keep last 10 images",
"selection": {
"tagStatus": "any",
"countType": "imageCountMoreThan",
"countNumber": 10
},
"action": {
"type": "expire"
}
}
]
}Delete Untagged Images
{
"rules": [
{
"rulePriority": 1,
"description": "Delete untagged images older than 1 day",
"selection": {
"tagStatus": "untagged",
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 1
},
"action": { "type": "expire" }
}
]
}Keep Production Tags
{
"rules": [
{
"rulePriority": 1,
"description": "Keep production images forever",
"selection": {
"tagStatus": "tagged",
"tagPrefixList": ["prod", "release"],
"countType": "imageCountMoreThan",
"countNumber": 9999
},
"action": { "type": "expire" }
},
{
"rulePriority": 2,
"description": "Delete dev images older than 7 days",
"selection": {
"tagStatus": "tagged",
"tagPrefixList": ["dev", "feature"],
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 7
},
"action": { "type": "expire" }
}
]
}Apply Policy
aws ecr put-lifecycle-policy \
--repository-name my-app \
--lifecycle-policy-text file://lifecycle-policy.jsonReplication
Cross-Region Replication
aws ecr put-replication-configuration \
--replication-configuration '{
"rules": [
{
"destinations": [
{"region": "eu-west-1", "registryId": "123456789012"},
{"region": "ap-northeast-1", "registryId": "123456789012"}
],
"repositoryFilters": [
{"filter": "prod", "filterType": "PREFIX_MATCH"}
]
}
]
}'Cross-Account Replication
aws ecr put-replication-configuration \
--replication-configuration '{
"rules": [
{
"destinations": [
{"region": "us-east-1", "registryId": "987654321098"}
]
}
]
}'Access Control
Repository Policy
Allow cross-account pull:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowPull",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::987654321098:root"
},
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability"
]
}
]
}Apply policy:
aws ecr set-repository-policy \
--repository-name my-app \
--policy-text file://policy.jsonAllow Lambda Access
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "LambdaECRImageRetrievalPolicy",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage"
],
"Condition": {
"StringLike": {
"aws:sourceArn": "arn:aws:lambda:us-east-1:123456789012:function:*"
}
}
}
]
}Pull Through Cache
Cache public registries in your private ECR:
# Create cache rule
aws ecr create-pull-through-cache-rule \
--ecr-repository-prefix docker-hub \
--upstream-registry-url registry-1.docker.io
# Pull via cache
docker pull 123456789012.dkr.ecr.us-east-1.amazonaws.com/docker-hub/library/nginx:latestSupported upstreams:
- Docker Hub
- Amazon ECR Public
- Quay
- GitHub Container Registry
Public ECR
Create Public Repository
aws ecr-public create-repository \
--repository-name my-public-app \
--catalog-data '{
"description": "My public application",
"operatingSystems": ["Linux"],
"architectures": ["x86-64", "ARM 64"]
}'Authenticate to Public ECR
aws ecr-public get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin public.ecr.awsPush to Public ECR
docker tag my-app:latest public.ecr.aws/a1b2c3d4/my-public-app:latest
docker push public.ecr.aws/a1b2c3d4/my-public-app:latestCI/CD Integration
GitHub Actions
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push
run: |
docker build -t ${{ secrets.ECR_REGISTRY }}/my-app:${{ github.sha }} .
docker push ${{ secrets.ECR_REGISTRY }}/my-app:${{ github.sha }}Docker Buildx (Multi-arch)
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest \
--push .Best Practices
Security
- Enable image scanning on push
- Use immutable tags for production
- Implement least-privilege repository policies
- Regularly review scan findings
Cost Optimization
- Implement lifecycle policies
- Delete untagged images promptly
- Use pull-through cache for public images
- Monitor storage usage
Operations
- Use semantic versioning for tags
- Replicate across regions for DR
- Tag images with build metadata
- Automate image cleanup