Skip to main content

ECR - Container Registry, Image Scanning, and Lifecycle Policies

Store, scan, and manage Docker container images in ECR with lifecycle policies, cross-account access, vulnerability scanning, and pull-through cache.

What you will learn

  • What ECR is and why teams use it instead of Docker Hub in AWS environments
  • Private vs Public ECR repositories
  • The ECR push and pull workflow from your CI/CD pipeline
  • Image scanning — basic and enhanced scanning with Inspector
  • Lifecycle policies — automatic deletion of old images to control costs
  • Cross-account access — sharing images between AWS accounts
  • Pull-through cache — caching public images inside ECR for reliability and speed
  • Image immutability — preventing tag overwrites in production
  • ECR in the ECS and EKS deployment pipeline

Why this matters

Every team running containers on AWS needs somewhere to store Docker images. Docker Hub is the public default — but it has rate limits, images are publicly visible by default, and pulling from Docker Hub adds external network dependency to every ECS or EKS deployment. ECR is the AWS-native answer. Images live in your AWS account, authentication is handled by IAM, images are private by default, no rate limits on pulls within AWS, and it integrates natively with ECS, EKS, and CodePipeline. Most importantly — your container deployments never depend on an external service being available.

What is Amazon ECR

ECR (Elastic Container Registry) is a fully managed Docker image registry. Think of it as Docker Hub but hosted inside your AWS account.

TEXT
Docker Hub:
Public registry — images visible to everyone by default
Rate limits on pulls (100-200 pulls per 6 hours for free accounts)
External dependency — your deployments depend on Docker Hub being up
Manual authentication for private images
Amazon ECR:
Private by default — only IAM-authorised principals can access
No pull rate limits within AWS — ECS and EKS pull freely
Integrated with IAM — same credentials your team already uses
No external dependency — images in your account, your region
Integrates natively with ECS, EKS, CodePipeline, CodeBuild

Private vs Public Repositories

Private ECR:

◈ DIAGRAM
One registry per AWS account per region
Multiple repositories inside the registry
Each repository holds one application's images with multiple tags
Registry: 123456789012.dkr.ecr.ap-south-1.amazonaws.com
Repositories:
.../devops-orders-api → orders-api:v1.0, orders-api:v1.1, orders-api:latest
.../devops-payment-api → payment-api:v2.3, payment-api:latest
.../devops-notification → notification:v1.0

Public ECR (ECR Public Gallery):

Bash
Images publicly accessible to anyone
URL: public.ecr.aws/your-alias/your-image
Use for: open-source projects, sharing base images publicly
Free to push and pull from AWS compute

The Push and Pull Workflow

The standard workflow for getting your Docker image into ECR and running on ECS or EKS:

Bash
Developer writes code
↓
CI/CD pipeline (CodeBuild, GitHub Actions) runs:
1. docker build
2. docker tag
3. docker push to ECR
↓
ECR stores the image
↓
ECS or EKS pulls the image and runs it

Step by step:

Bash
## Step 1 — Authenticate Docker to ECR (token valid 12 hours)
aws ecr get-login-password --region ap-south-1 | \
docker login \
--username AWS \
--password-stdin \
123456789012.dkr.ecr.ap-south-1.amazonaws.com
## Step 2 — Build your image
docker build -t devops-orders-api:v1.2 .
## Step 3 — Tag with full ECR URI
docker tag devops-orders-api:v1.2 \
123456789012.dkr.ecr.ap-south-1.amazonaws.com/devops-orders-api:v1.2
docker tag devops-orders-api:v1.2 \
123456789012.dkr.ecr.ap-south-1.amazonaws.com/devops-orders-api:latest
## Step 4 — Push both tags
docker push 123456789012.dkr.ecr.ap-south-1.amazonaws.com/devops-orders-api:v1.2
docker push 123456789012.dkr.ecr.ap-south-1.amazonaws.com/devops-orders-api:latest

ECR stores layers. If two images share the same base layer, ECR stores it only once. Subsequent pushes with the same layers are instant — only new layers are uploaded.

Image Scanning — Vulnerability Detection

ECR scans your images for known security vulnerabilities in OS packages and application libraries.

Basic Scanning (free):

TEXT
Uses the open-source Clair scanner
Scans on push or on demand
Checks against CVE databases
Shows: HIGH, MEDIUM, LOW severity findings per image

Enhanced Scanning (paid — uses Amazon Inspector):

TEXT
Uses Inspector under the hood
Continuous scanning — re-scans automatically when new CVEs are discovered
Covers: OS packages AND application dependencies (Node.js, Python packages, Java jars)
Risk score per finding
Findings appear in Inspector console
A new CVE is published for Log4j
All images in ECR are automatically re-scanned
Any image containing the vulnerable Log4j version is flagged immediately

Enable scanning at repository level:

◈ DIAGRAM
ECR → Repositories → devops-orders-api → Edit
Scan on push: Enable → Save
After every push → ECR scans automatically
View results: ECR → Repositories → devops-orders-api → Images → click image → Vulnerabilities

Lifecycle Policies — Control Storage Costs

Every CI/CD push creates a new image. Without lifecycle policies, images accumulate indefinitely. A busy team pushing 10 images per day has 300 images per month — most of them old versions nobody will ever use.

Lifecycle policies automatically expire and delete old images based on rules you define.

Common policy patterns:

TEXT
Keep only the last 10 images:
Rule: expire images when count exceeds 10
Effect: always have the 10 most recent, older ones deleted automatically
Keep tagged releases, expire untagged:
Rule 1: keep any image tagged with v* (release tags) — never expire
Rule 2: expire untagged images after 7 days
Effect: production releases kept forever, dev builds cleaned up weekly
Keep last 30 days only:
Rule: expire images older than 30 days
Effect: sliding window of recent images

Setting up in the console:

◈ DIAGRAM
ECR → Repositories → your-repo → Lifecycle Policy → Create rule
Tag status: Any Image count more than: 10 Action: Expire
Save and run
Remember

Set up a lifecycle policy when you create the repository — not after 6 months when you notice storage costs have grown. Once a repository has thousands of images, cleaning up requires deleting them one by one.

Image Immutability — Prevent Tag Overwriting

By default, you can push a new image with the same tag and it overwrites the old one. latest pushed today replaces latest from yesterday.

◈ DIAGRAM
Without immutability:
Friday: push orders-api:v1.2 → ECS runs this
Monday: push orders-api:v1.2 (buggy build) → same tag, different image
ECS pulls "v1.2" and gets the buggy Monday build
Friday's working build is gone
With image immutability:
Attempt to push orders-api:v1.2 again → ECR rejects it with an error
Every tag is permanent — cannot be overwritten
Rollback is always possible — the old image is guaranteed to still be there

Enable at repository level:

◈ DIAGRAM
ECR → Repositories → your-repo → Edit → Image tag mutability: Immutable → Save

Cross-Account Access

Teams often need to share images between accounts — a shared infrastructure account stores base images, application accounts pull from it.

Grant another account pull access via repository policy:

◈ DIAGRAM
ECR → your-repo → Permissions → Edit policy JSON
JSON
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::987654321098:root"
},
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchCheckLayerAvailability",
"ecr:BatchGetImage"
]
}
]
}

Account 987654321098 can now pull images from this repository. They still need to authenticate using their own credentials and call ecr:GetAuthorizationToken in your account.

Pull-Through Cache — Cache Public Images Locally

Your ECS tasks need nginx:latest, node:18, or python:3.12 from Docker Hub. Every pull goes to Docker Hub — rate limits apply, and your deployment depends on Docker Hub availability.

Pull-through cache creates a mirrored copy of public registries inside your ECR.

Bash
Configure pull-through cache rule:
Upstream: registry-1.docker.io (Docker Hub)
ECR namespace: dockerhub
First pull of nginx:latest:
ECS → ECR (dockerhub/nginx:latest) → ECR fetches from Docker Hub → caches in your ECR
Subsequent pulls:
ECS → ECR (dockerhub/nginx:latest) → served from your ECR cache (no Docker Hub call)

No Docker Hub rate limits. No external dependency during deployments. Images cached in your region.

Supports: Docker Hub, Quay, GitHub Container Registry, Kubernetes (registry.k8s.io), Amazon ECR Public.

Hands-on Lab — Create Repository, Push Image, Set Lifecycle Policy

Step 1 — Create an ECR repository

◈ DIAGRAM
ECR → Repositories → Create repository
Visibility: Private
Repository name: devops-orders-api
Image tag mutability: Immutable
Scan on push: Enable
Create repository

Step 2 — Authenticate and push a Docker image

◈ DIAGRAM
Click on devops-orders-api → View push commands
Follow the 4 commands shown (authenticated for your account and region):
Bash
## The console shows your exact commands — copy from there
## They follow this pattern:
## 1. Login
aws ecr get-login-password --region ap-south-1 | \
docker login --username AWS --password-stdin \
YOUR-ACCOUNT-ID.dkr.ecr.ap-south-1.amazonaws.com
## 2. Build (use any simple Dockerfile)
echo "FROM nginx:alpine" > Dockerfile
docker build -t devops-orders-api .
## 3. Tag
docker tag devops-orders-api:latest \
YOUR-ACCOUNT-ID.dkr.ecr.ap-south-1.amazonaws.com/devops-orders-api:v1.0
## 4. Push
docker push \
YOUR-ACCOUNT-ID.dkr.ecr.ap-south-1.amazonaws.com/devops-orders-api:v1.0

Step 3 — View the image and scan results

◈ DIAGRAM
ECR → devops-orders-api → Images
Your image appears with size, push time, and scan status
Click the image → Vulnerabilities tab
See any findings from the scan (nginx:alpine typically has very few)

Step 4 — Create a lifecycle policy

◈ DIAGRAM
ECR → devops-orders-api → Lifecycle Policy → Create rule
Rule priority: 1
Rule description: Keep only last 5 images
Image status: Any
Match criteria: Image count more than 5
Action on review: Expire
Save and run test
Review results shows which images would be deleted if the policy ran now.
Save → policy is now active for all future pushes.

Step 5 — Cleanup

◈ DIAGRAM
ECR → devops-orders-api → select all images → Delete
ECR → Repositories → devops-orders-api → Delete repository
Confirm deletion

Common Mistakes to Avoid

Common Mistake

Not setting a lifecycle policy and discovering 6 months later that image storage costs are significant. ECR charges per GB stored. A repository with 2,000 old images adds up. Set the policy when you create the repository.

Common Mistake

The most common ECS deployment failure is an ECR image pull error. The cause is almost always a missing IAM permission on the ECS Task Execution Role. It needs: ecr:GetAuthorizationToken, ecr:BatchCheckLayerAvailability, and ecr:GetDownloadUrlForLayer. Check the execution role first when a container fails to start.

Tip

Use versioned tags alongside latest. Always push both :v1.2 and :latest. ECS and EKS should reference the specific version tag in production — not latest. The :latest tag is for humans to see what the current version is. Deployments referencing :latest make rollbacks impossible and create unpredictable behaviour.

Resources

AWS Direct Connect vs Site-to-Site VPN Failover

AWS Direct Connect vs Site-to-Site VPN Failover

Direct Connect vs VPN isn't really either/or for production — it's a primary-plus-failover pattern. Here's how to design it, and when either/or is right.

5 min read•Aug 2026
Lambda vs Fargate vs EC2 Spot: The Cost Crossover

Lambda vs Fargate vs EC2 Spot: The Cost Crossover

Lambda vs Fargate vs EC2 Spot, at the crossover where Lambda stops being cheaper — 2026 pricing, invocation thresholds, and interruption math.

5 min read•Aug 2026
Secrets Manager vs Parameter Store vs Vault

Secrets Manager vs Parameter Store vs Vault

AWS Secrets Manager, Parameter Store, and HashiCorp Vault compared for 2026 - cost math, rotation, multi-cloud fit, and the Vault-to-OpenBao fork.

5 min read•Aug 2026
AWS VPC Security: Hardening Every Layer

AWS VPC Security: Hardening Every Layer

Most cloud security incidents start with a misconfigured VPC. Here's how to harden every layer — subnets, Security Groups, NACLs, and IAM — for production.

5 min read•Jul 2026
Event-Driven Architecture on AWS Explained

Event-Driven Architecture on AWS Explained

Event-driven architecture on AWS decouples services and absorbs traffic spikes using SQS, SNS, EventBridge, and Lambda — workflows that scale themselves.

5 min read•Jul 2026
S3 vs RDS vs DynamoDB: Choosing AWS Storage

S3 vs RDS vs DynamoDB: Choosing AWS Storage

Choosing S3, RDS, or DynamoDB wrong costs you in performance, cost, and scalability. Here is a practical decision guide based on your actual access patterns.

5 min read•Jul 2026
AWS Cost Optimisation: Cut Cloud Bills 40-60%

AWS Cost Optimisation: Cut Cloud Bills 40-60%

AWS bills surprise teams every month. Here are the 8 concrete actions that cut cloud spend by 40-60% without touching your application architecture.

5 min read•Jul 2026
EC2 vs Lambda vs Fargate: Choosing AWS Compute

EC2 vs Lambda vs Fargate: Choosing AWS Compute

EC2, Lambda, or Fargate — choosing the wrong AWS compute option costs you money and performance. Here is exactly when to use each one in production.

5 min read•Jul 2026

Explore More in AWS Messaging, Analytics, and Containers

All 6 Topics

Frequently Asked Questions

Is ECR - Container Registry, Image Scanning, and Lifecycle Policies free to learn on DevOps Network?

Yes - this topic, like everything on DevOps Network, is 100% free with no paywall or sign-up gate.

What does the ECR - Container Registry, Image Scanning, and Lifecycle Policies topic cover?

Store, scan, and manage Docker container images in ECR with lifecycle policies, cross-account access, vulnerability scanning, and pull-through cache.