ECR (Container Registry)
Amazon ECR (Elastic Container Registry) is a fully managed Docker container registry. It stores your container images and integrates natively with ECS, EKS, Lambda, and CodeBuild.
How ECR Fits In
Section titled “How ECR Fits In”Build (CodeBuild / GitHub Actions) │ ▼docker push ──► ECR Repository ──► ECS / EKS / Lambda pulls image │ ├── Image scanning (vulnerabilities) └── Lifecycle policies (cleanup old images)Core Concepts
Section titled “Core Concepts”| Concept | What It Is |
|---|---|
| Registry | Your account’s ECR registry (123456789012.dkr.ecr.us-east-1.amazonaws.com) |
| Repository | A collection of images for one application (like a Docker Hub repo) |
| Image | A Docker image identified by tag or digest |
| Tag | A label for an image (latest, v1.2.3, abc123) — mutable (can be moved) |
| Digest | A SHA256 hash that uniquely and immutably identifies an image |
Basic Operations
Section titled “Basic Operations”Create a Repository
Section titled “Create a Repository”aws ecr create-repository --repository-name my-app \ --image-scanning-configuration scanOnPush=true \ --encryption-configuration encryptionType=KMSAuthenticate Docker
Section titled “Authenticate Docker”ECR uses temporary tokens — you must authenticate before push/pull:
# Login (token valid for 12 hours)aws ecr get-login-password --region us-east-1 | \ docker login --username AWS --password-stdin \ 123456789012.dkr.ecr.us-east-1.amazonaws.comBuild, Tag, and Push
Section titled “Build, Tag, and Push”# Build the imagedocker build -t my-app .
# Tag for ECRdocker tag my-app:latest \ 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest
# Also tag with the commit SHA for traceabilitydocker tag my-app:latest \ 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:abc123def
# Pushdocker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latestdocker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:abc123defPull an Image
Section titled “Pull an Image”docker pull 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latestECS and EKS pull images automatically using the task/pod IAM role — no manual docker pull needed.
Image Tagging Strategy
Section titled “Image Tagging Strategy”| Strategy | Tag Example | Pros | Cons |
|---|---|---|---|
latest | latest | Simple | Don’t know which version is running; not reproducible |
| Git SHA | abc123def | Traceable to exact commit | Not human-readable |
| Semantic version | v1.2.3 | Clear release versioning | Must manage version bumps |
| Both | v1.2.3 + abc123def | Best of both worlds | Two tags per push |
Best practice: Always push a git SHA tag alongside any other tag. This makes it trivial to trace a running container back to its source code.
Image Tag Immutability
Section titled “Image Tag Immutability”# Enable immutability (prevents overwriting tags)aws ecr put-image-tag-mutability \ --repository-name my-app \ --image-tag-mutability IMMUTABLEWith immutability enabled, pushing to an existing tag fails. This prevents accidental overwrites and ensures v1.2.3 always refers to the same image. Note: this means you can’t use a mutable latest tag.
Lifecycle Policies
Section titled “Lifecycle Policies”Lifecycle policies automatically clean up old images to save storage costs:
aws ecr put-lifecycle-policy --repository-name my-app \ --lifecycle-policy-text '{ "rules": [ { "rulePriority": 1, "description": "Keep last 10 tagged images", "selection": { "tagStatus": "tagged", "tagPrefixList": ["v"], "countType": "imageCountMoreThan", "countNumber": 10 }, "action": {"type": "expire"} }, { "rulePriority": 2, "description": "Delete untagged images older than 7 days", "selection": { "tagStatus": "untagged", "countType": "sinceImagePushed", "countUnit": "days", "countNumber": 7 }, "action": {"type": "expire"} } ] }'This keeps the 10 most recent version-tagged images and deletes untagged images after 7 days.
Image Scanning
Section titled “Image Scanning”ECR can scan images for known vulnerabilities (CVEs):
Scan Types
Section titled “Scan Types”| Type | When | Coverage |
|---|---|---|
| Basic scanning | On push or manual trigger | OS package vulnerabilities |
| Enhanced scanning (Inspector) | Continuous | OS + programming language vulnerabilities (pip, npm, etc.) |
Enable Enhanced Scanning
Section titled “Enable Enhanced Scanning”aws ecr put-registry-scanning-configuration \ --scan-type ENHANCED \ --rules '[{ "repositoryFilters": [{"filter": "*", "filterType": "WILDCARD"}], "scanFrequency": "CONTINUOUS_SCAN" }]'Viewing Scan Results
Section titled “Viewing Scan Results”aws ecr describe-image-scan-findings \ --repository-name my-app \ --image-id imageTag=latestFindings include CVE ID, severity, affected package, and fixed version — same as Inspector findings.
Cross-Account Access
Section titled “Cross-Account Access”Share images across AWS accounts using a repository policy:
{ "Version": "2012-10-17", "Statement": [{ "Sid": "AllowCrossAccountPull", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::987654321098:root" }, "Action": [ "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage", "ecr:BatchCheckLayerAvailability" ] }]}The other account can now pull images from your repository. Useful for shared base images or a central registry account.
Cross-Region Replication
Section titled “Cross-Region Replication”Automatically replicate images to other regions for faster pulls and disaster recovery:
aws ecr put-replication-configuration --replication-configuration '{ "rules": [{ "destinations": [ {"region": "eu-west-1", "registryId": "123456789012"}, {"region": "ap-southeast-1", "registryId": "123456789012"} ] }]}'ECR in CI/CD
Section titled “ECR in CI/CD”GitHub Actions
Section titled “GitHub Actions”- name: Login to ECR uses: aws-actions/amazon-ecr-login@v2
- name: Build and push env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} IMAGE_TAG: ${{ github.sha }} run: | docker build -t $REGISTRY/my-app:$IMAGE_TAG . docker push $REGISTRY/my-app:$IMAGE_TAGCodeBuild
Section titled “CodeBuild”phases: pre_build: commands: - aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_REGISTRY build: commands: - docker build -t $ECR_REGISTRY/my-app:$CODEBUILD_RESOLVED_SOURCE_VERSION . - docker push $ECR_REGISTRY/my-app:$CODEBUILD_RESOLVED_SOURCE_VERSIONECR Public
Section titled “ECR Public”ECR Public hosts public container images (like Docker Hub) at public.ecr.aws:
# Create a public repositoryaws ecr-public create-repository --repository-name my-public-app
# Push to publicdocker tag my-app:latest public.ecr.aws/a1b2c3d4/my-public-app:latestdocker push public.ecr.aws/a1b2c3d4/my-public-app:latestFree tier: 50 GB storage, 500 GB/month data transfer for authenticated users.
ECR vs Other Registries
Section titled “ECR vs Other Registries”| ECR | Docker Hub | GitHub Container Registry | |
|---|---|---|---|
| Private images | Yes (default) | Paid | Yes (free for public) |
| AWS integration | Native (IAM, ECS, EKS) | Manual auth | Manual auth |
| Scanning | Built-in (basic + Inspector) | Paid | Basic |
| Lifecycle policies | Yes | No | No |
| Cross-region replication | Yes | No | No |
| Cost | $0.10/GB/month storage | Free (public), paid (private) | Free (limited) |
Key Takeaways
Section titled “Key Takeaways”- ECR stores Docker images with native IAM authentication — no Docker Hub credentials needed.
- Always tag images with the git SHA for traceability alongside version tags.
- Use lifecycle policies to automatically delete old images and control storage costs.
- Enable scan on push (basic) or enhanced scanning (Inspector) to catch vulnerabilities before deployment.
- Use cross-account policies for shared base images and replication for multi-region deployments.
- Image tag immutability prevents accidental overwrites — use it for release tags.