4. Container registry with ECR
ECR is AWS's private Docker registry. Push your image here so ECS can pull and run it.
The image you built with docker build in Chapter 27 lives on your laptop. ECS, running on Fargate in a different AWS region, has no way to read it from there. The fix is a registry: a place ECR pulls the image from when the task starts. ECR is the AWS-native option, and it's the one that integrates cleanly with the IAM permissions ECS already uses, so the pull credential is one less moving part to manage.
Creating the ECR repository
ECR organizes images into repositories. Each repository holds versions of one application. You'll create a repository for your News Aggregator API, then push your Docker image there.
Make: Create an ECR repository via AWS CLI:
aws ecr create-repository \
--repository-name news-aggregator-api \
--region us-east-1 \
--image-scanning-configuration scanOnPush=true
# Output:
{
"repository": {
"repositoryArn": "arn:aws:ecr:us-east-1:123456789012:repository/news-aggregator-api",
"registryId": "123456789012",
"repositoryName": "news-aggregator-api",
"repositoryUri": "123456789012.dkr.ecr.us-east-1.amazonaws.com/news-aggregator-api",
"createdAt": "2024-12-10T10:30:00+00:00",
"imageScanningConfiguration": {
"scanOnPush": true
}
}
}
Key field: The repositoryUri is where you'll push images. Save this URI: you'll use it for tagging and pushing your Docker image.
What scanOnPush=true does: ECR automatically scans images for known security vulnerabilities (CVEs) when you push them. You'll get a report showing any security issues in your dependencies. This is free within the Free Tier scanning limits.
Check: Verify the repository exists:
aws ecr describe-repositories --region us-east-1
# Shows your news-aggregator-api repository
Authenticating Docker with ECR
ECR repositories are private by default. Before pushing images, Docker needs authentication credentials. The AWS CLI generates temporary credentials that expire after 12 hours. You'll authenticate each session before pushing images.
Make: Authenticate Docker with ECR:
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin \
123456789012.dkr.ecr.us-east-1.amazonaws.com
# Replace 123456789012 with your actual AWS account ID
# Get it from: aws sts get-caller-identity --query Account --output text
# Output on success:
Login Succeeded
What this does: The AWS CLI retrieves temporary Docker login credentials and pipes them to docker login. Docker stores these credentials locally until they expire. Now Docker can push and pull images from your ECR repository.
Credentials expire after 12 hours. If you get authentication errors later, rerun this command to refresh your Docker authentication with ECR.
Pushing the API image to ECR
Before pushing to ECR, you need to tag your local Docker image with the ECR repository URI. Docker uses tags to map images to registries. The tag format is: repositoryUri:version.
Make: Tag and push your News API image:
# Get your ECR repository URI
ECR_URI=$(aws ecr describe-repositories \
--repository-names news-aggregator-api \
--query 'repositories[0].repositoryUri' \
--output text)
echo "ECR URI: $ECR_URI"
# Tag your local image
# If your image is called "news-api:latest" from Chapter 27:
docker tag news-api:latest $ECR_URI:latest
docker tag news-api:latest $ECR_URI:v1.0.0
# Push both tags to ECR
docker push $ECR_URI:latest
docker push $ECR_URI:v1.0.0
Check: Verify images in ECR:
aws ecr list-images \
--repository-name news-aggregator-api \
--region us-east-1
# Output shows your images:
{
"imageIds": [
{
"imageDigest": "sha256:abc123...",
"imageTag": "latest"
},
{
"imageDigest": "sha256:abc123...",
"imageTag": "v1.0.0"
}
]
}
Your Docker image is now in ECR, accessible to AWS services. ECS will pull from this registry when deploying containers. The image is private; only IAM principals in your AWS account can read it.
Image tagging strategies
Tags are how a task definition picks which image to pull. Three patterns cover the cases that matter, and they stack: an image can carry all three at the same time, and each one answers a different question.
latestfor the current production release. Convenient for ad-hoc testing, but ambiguous: re-pushing:latestmoves the pointer, so two ECS tasks started a day apart can be running different code. Don't pin production task definitions to:latestfor that reason.- Semantic version for release management. Tags like
v1.0.0,v1.1.0,v2.0.0are immutable once pushed and read well in deploy logs. They're what the task definition should pin to in production, since a rollback is a one-line change back to the previous tag. - Commit SHA for exact traceability. A tag like
sha-abc123dties a running container back to a specific source commit. CI/CD pipelines (Chapter 29) lean on this so an alert points cleanly at one revision rather than a range.
The practical pattern: push all three on each release. The task definition pins to the semver tag; the commit-SHA tag is there for forensic work; :latest is the convenience handle for one-off pulls.
# Get current Git commit SHA
COMMIT_SHA=$(git rev-parse --short HEAD)
# Tag with all three strategies
docker tag news-api:latest $ECR_URI:latest
docker tag news-api:latest $ECR_URI:v1.2.3
docker tag news-api:latest $ECR_URI:sha-$COMMIT_SHA
# Push all tags
docker push $ECR_URI:latest
docker push $ECR_URI:v1.2.3
docker push $ECR_URI:sha-$COMMIT_SHA
Next, in section 5, we stand up the RDS Postgres instance and the ElastiCache Redis cluster the API needs, and scope each one's security group so only the ECS service can reach them.