Using AWS ECR as a Universal OCI Repository¶
Written by:
Igor Gorovyy
DevOps Engineer Lead & Senior Solutions Architect
Introduction¶
In the modern world of DevOps and Cloud Native development, artifact management is becoming increasingly complex. Each type of artifact traditionally required a separate repository: Docker Hub for containers, Artifactory for binaries, MLflow for machine learning models, etc. This created a "zoo" of services that is difficult to maintain and scale.
Thanks to the emergence of the Open Container Initiative (OCI), a unified standard for all types of artifacts has appeared. This has allowed companies to create universal repositories that can store any artifacts: from Docker images to machine learning models.
Amazon Elastic Container Registry (ECR) is not just a registry for Docker images, but a full-fledged OCI-compliant repository. Since 2022, AWS ECR has supported the OCI Artifact specification, allowing it to store any artifacts that comply with this standard.
In this article, I will cover: - How to effectively use AWS ECR for different types of artifacts - How to eliminate the need for multiple repositories - Practical examples of working with different types of artifacts - Best practices and security recommendations
Benefits of Using ECR as a Universal Repository¶
- Single Access Point: All artifacts in one place with a unified authentication system
- AWS Integration: Native support for IAM, CloudWatch, KMS
- Cost Effectiveness: Single billing system and cost optimization
- Simplified Management: Common lifecycle policies and replication
- Security: Built-in vulnerability scanning and encryption
Prerequisites¶
Before we dive into practical examples, let's set up the necessary tools and create our first repository.
Required Tools¶
For working with ECR as a universal repository, we'll need:
- AWS CLI: For interacting with AWS services
- Helm CLI: For working with Helm charts
- ORAS CLI: For working with OCI artifacts
- Terraform >=1.5: For infrastructure as code
Creating and Configuring the Repository¶
First, let's create a repository in ECR:
aws ecr create-repository --repository-name my-universal-repo \
--image-scanning-configuration scanOnPush=true \
--region eu-central-1
This repository will be our universal storage for all types of artifacts.
Authentication¶
To work with ECR, you need to authenticate:
aws ecr get-login-password \
| docker login --username AWS --password-stdin <aws_account_id>.dkr.ecr.eu-central-1.amazonaws.com
Working with Different Types of Artifacts¶
Let's look at how to work with different types of artifacts in our universal repository.
1. Docker Images¶
Docker images are the classic use case for ECR. The process of working with them is simple and straightforward:
# Build
docker build -t my-app .
# Tag
docker tag my-app:latest <aws_id>.dkr.ecr.eu-central-1.amazonaws.com/my-universal-repo:my-app-v1
# Push
docker push <aws_id>.dkr.ecr.eu-central-1.amazonaws.com/my-universal-repo:my-app-v1
Key benefits of using ECR for Docker images: - Automatic vulnerability scanning - Immutable tags - Integration with ECS/EKS - Cross-region replication capability
2. Helm Charts via OCI¶
Helm 3 added OCI support, allowing charts to be stored directly in ECR without the need for a separate Helm repository.
# Enable OCI support
export HELM_EXPERIMENTAL_OCI=1
# Create helm chart
helm create my-chart
# Package
helm package my-chart
# Push to ECR
helm push my-chart-0.1.0.tgz oci://<aws_id>.dkr.ecr.eu-central-1.amazonaws.com/my-universal-repo
# Install
helm install mychart oci://<aws_id>.dkr.ecr.eu-central-1.amazonaws.com/my-universal-repo --version 0.1.0
Benefits of storing Helm charts in ECR: - Versioning and access control - Single access point with Docker images - Possibility to use in GitOps processes
3. Terraform Providers and Modules¶
With version 1.5, Terraform added native support for OCI registries for modules. This allows using ECR as a source for modules and providers.
3.1. Publishing Terraform Provider/Module¶
# Module structure
tree my-module/
├── main.tf
├── variables.tf
├── outputs.tf
# Archive
tar -czf my-module.tar.gz my-module/
# Push using oras
oras push <aws_id>.dkr.ecr.eu-central-1.amazonaws.com/my-universal-repo:tf-my-module-v1 \
--artifact-type application/vnd.terraform.module \
my-module.tar.gz
3.2. Using as a Module in Terraform¶
module "my_module" {
source = "oci::<aws_id>.dkr.ecr.eu-central-1.amazonaws.com/my-universal-repo:tf-my-module-v1"
}
Benefits of storing Terraform modules in ECR: - Versioning and access control - Private modules without additional services - Integration with existing CI/CD pipelines
4. ML Models¶
One of the most interesting capabilities is storing machine learning models. ECR can replace specialized ML registries for many use cases.
Basic Example:¶
# Upload model
oras push <aws_id>.dkr.ecr.eu-central-1.amazonaws.com/my-universal-repo:ml-my-model-v1 \
--artifact-type application/vnd.model.mlflow \
model.pkl
Advanced Example with Metadata:¶
oras push <aws_id>.dkr.ecr.eu-central-1.amazonaws.com/my-universal-repo:ml-my-model-v2 \
--artifact-type application/vnd.model \
"model.onnx" \
"metadata.json"
📌 It's important to understand that ECR doesn't validate the MIME type - it just stores the artifact with the specified type. However, other tools can use this type for filtering and identifying artifacts.
Working with ML Models in Detail¶
Metadata Structure¶
For effective ML model management, it's important to have well-structured metadata. Here's an example:
{
"model_name": "resnet50",
"version": "1.0.0",
"framework": "onnx",
"input_shape": [1, 3, 224, 224],
"output_classes": 1000,
"trained_on": "imagenet",
"accuracy_top1": 0.76,
"accuracy_top5": 0.93,
"created_at": "2025-07-08T12:00:00Z"
}
Such metadata allows: - Tracking model versions - Documenting parameters and characteristics - Simplifying search and selection of needed versions - Automating deployment processes
Model Publication Automation¶
To simplify the model publication process, you can use a script:
#!/bin/bash
set -e
# === Arguments ===
MODEL_FILE=${1:-"model.onnx"}
META_FILE=${2:-"metadata.json"}
TAG=${3:-"resnet50-v1"}
# === AWS ECR Configuration ===
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REGION=eu-central-1
REPO_NAME=ml-registry
REPO_URL="$AWS_ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO_NAME"
# === Authentication ===
aws ecr get-login-password \
| oras login --username AWS --password-stdin $REPO_URL
# === Push ===
echo "🚀 Uploading model [$MODEL_FILE] and metadata [$META_FILE] to [$REPO_URL:$TAG]"
oras push $REPO_URL:$TAG \
--artifact-type application/vnd.model \
"$MODEL_FILE" \
"$META_FILE"
echo "✅ Done. Artifact pushed as $REPO_URL:$TAG"
Common MIME Types for ML Artifacts¶
When working with ML models, it's important to specify the correct MIME types:
MIME Type | Purpose |
---|---|
application/vnd.model | General ML artifact |
application/vnd.model.mlflow | MLflow model |
application/vnd.model.onnx | ONNX model |
application/vnd.model.torch | TorchScript |
application/vnd.model.keras | Keras model |
Working with YOLO Models¶
Working with popular computer vision models like YOLO is of particular interest. There are three main approaches to storing them in ECR:
1. As a Docker Image (Recommended for Deployment)¶
FROM ultralytics/yolov5:latest
# Add our model
COPY best.pt /models/best.pt
CMD ["python3", "detect.py", "--weights", "/models/best.pt", "--source", "0"]
Build and publish:
docker build -t yolo-inference .
docker tag yolo-inference <aws_id>.dkr.ecr.eu-central-1.amazonaws.com/yolo:v5
docker push <aws_id>.dkr.ecr.eu-central-1.amazonaws.com/yolo:v5
2. As an OCI Artifact via ORAS¶
oras push <ecr_repo>:yolov5-v1 \
--artifact-type application/vnd.model.pytorch \
best.pt \
metadata.json
Metadata for YOLO model:
{
"model_name": "yolov5",
"framework": "pytorch",
"version": "6.2",
"input_shape": [1, 3, 640, 640],
"trained_on": "coco",
"classes": 80
}
3. As an ONNX Model¶
YOLOv5 supports export to ONNX format:
python export.py --weights best.pt --include onnx
Publishing ONNX version:
oras push <ecr_repo>:yolov5-onnx \
--artifact-type application/vnd.model.onnx \
best.onnx \
metadata.json
Approach Comparison¶
Format | Pros | Cons |
---|---|---|
Docker image | - Ready to run in ECS/EKS/Lambda - Includes all dependencies - Easier deployment |
- Large size - Less flexibility - Harder model updates |
.pt + ORAS | - Compact size - Convenient as model registry - Easy versioning |
- Requires separate runtime environment - Additional environment configuration |
ONNX + ORAS | - Cross-framework compatibility - Optimized inference - Easy integration |
- Not all YOLO features available - Possible performance differences |
Security and Access Management¶
IAM Policies¶
Basic policy for read/write access to ECR:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload"
],
"Resource": "*"
}
]
}
Cross-Account Access¶
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCrossAccountPull",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::444455556666:root"
},
"Action": [
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer"
]
}
]
}
Cost Management and Optimization¶
ECR pricing consists of three components:
- Storage: $0.10 per GB-month
- Data Transfer:
- Inbound: Free
- Outbound: Based on AWS region and volume
- API Requests:
- First 10 million requests per month: $0.01 per request
- Over 10 million requests: $0.008 per request
Cost Optimization Tips¶
- Use lifecycle policies to remove unused artifacts
- Implement image tagging strategy
- Consider multi-region replication costs
- Use AWS Organizations for consolidated billing
- Monitor costs with AWS Cost Explorer
CI/CD Integration¶
GitHub Actions Example¶
name: Publish to ECR
on:
push:
branches: [ main ]
paths:
- 'models/**'
- 'charts/**'
- 'terraform/**'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-central-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Publish artifacts
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: my-universal-repo
IMAGE_TAG: ${{ github.sha }}
run: |
# Publish Docker images
if [ -f Dockerfile ]; then
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
fi
# Publish Helm charts
if [ -d charts ]; then
for chart in charts/*; do
if [ -d "$chart" ]; then
helm package $chart
helm push ${chart##*/}-*.tgz oci://$ECR_REGISTRY/$ECR_REPOSITORY
fi
done
fi
# Publish ML models
if [ -d models ]; then
for model in models/*.onnx; do
if [ -f "$model" ]; then
oras push $ECR_REGISTRY/$ECR_REPOSITORY:${model##*/}-$IMAGE_TAG \
--artifact-type application/vnd.model.onnx \
"$model" \
"${model%.*}.json"
fi
done
fi
Terraform Configuration¶
resource "aws_ecr_repository" "universal_repo" {
name = "my-universal-repo"
image_tag_mutability = "IMMUTABLE"
image_scanning_configuration {
scan_on_push = true
}
encryption_configuration {
encryption_type = "KMS"
kms_key = aws_kms_key.ecr_key.arn
}
tags = {
Environment = "production"
Purpose = "universal-artifacts"
}
}
resource "aws_ecr_lifecycle_policy" "cleanup_policy" {
repository = aws_ecr_repository.universal_repo.name
policy = jsonencode({
rules = [
{
rulePriority = 1
description = "Keep last 10 versions of each artifact"
selection = {
tagStatus = "tagged"
tagPrefixList = ["v"]
countType = "imageCountMoreThan"
countNumber = 10
}
action = {
type = "expire"
}
},
{
rulePriority = 2
description = "Remove inactive artifacts older than 90 days"
selection = {
tagStatus = "untagged"
countType = "sinceImagePushed"
countUnit = "days"
countNumber = 90
}
action = {
type = "expire"
}
}
]
})
}
Conclusions and Recommendations¶
- Structure Planning:
- Develop a clear naming strategy
- Define lifecycle policies
-
Document processes and standards
-
Security:
- Use least privilege access
- Regularly update security policies
-
Configure vulnerability scanning
-
Automation:
- Create repeatable processes
- Use CI/CD for publication
-
Automate testing and validation
-
Monitoring:
- Track resource usage
- Set up alerts
- Regularly analyze costs
AWS ECR as a universal OCI repository provides a powerful and flexible platform for managing various artifacts. Proper setup and usage can significantly simplify development and deployment processes while ensuring a high level of security and control.