Open Container Initiative Repository Capabilities: A Comprehensive Guide

READER BEWARE: THE FOLLOWING WRITTEN ENTIRELY BY AI WITHOUT HUMAN EDITING.

Introduction

The Open Container Initiative (OCI) has revolutionized how we store and distribute containerized applications and related artifacts. OCI registries have evolved from simple container image repositories to versatile artifact stores that support a wide range of content types, security mechanisms, and client integrations. This comprehensive guide explores the full capabilities of OCI repositories, from object storage to security features, and provides practical insights for leveraging these capabilities in modern DevOps workflows.

What is an OCI Repository?

An OCI repository is a standardized storage system that implements the OCI Distribution Specification. It provides a common interface for storing, discovering, and retrieving container images and other artifacts. The OCI Distribution Specification defines the API contract that all OCI-compliant registries must implement, ensuring interoperability across different registry implementations.

Key characteristics of OCI repositories include:

  • Standardized API: All OCI-compliant registries expose the same REST API endpoints
  • Content-addressable storage: Objects are identified by their cryptographic digest
  • Layered architecture: Images and artifacts are composed of reusable layers
  • Metadata support: Manifests contain rich metadata about stored objects
  • Tag-based versioning: Human-readable tags reference specific versions of artifacts

Types of Objects Stored in OCI Repositories

OCI repositories support a diverse range of object types beyond traditional container images:

1. Container Images

The primary use case for OCI repositories is storing container images. These images contain everything needed to run a containerized application:

  • Base layers: Operating system files and dependencies
  • Application layers: Application code, libraries, and runtime dependencies
  • Configuration: Environment variables, exposed ports, and entry points
  • Metadata: Labels, annotations, and build information

2. Helm Charts

Helm charts, the Kubernetes package format, can be stored as OCI artifacts. This provides several advantages:

  • Unified storage: Charts alongside container images in the same registry
  • Version management: Leverage OCI tagging for chart versioning
  • Security: Apply the same security policies to charts as container images
  • Distribution: Use standard OCI clients to push and pull charts

Example of storing a Helm chart:

helm package ./my-chart
helm push my-chart-1.0.0.tgz oci://registry.example.com/charts

3. Container Signatures and Attestations

Cryptographic signatures and software bill of materials (SBOMs) can be stored alongside container images:

  • Cosign signatures: Keyless or key-based signatures for image verification
  • In-toto attestations: Build provenance and supply chain metadata
  • SBOM documents: Software composition analysis data in SPDX or CycloneDX format
  • Vulnerability scan results: Security assessment reports

4. Configuration Files and Policies

OCI repositories can store configuration artifacts:

  • Kubernetes manifests: YAML configurations for deployments
  • Policy bundles: Open Policy Agent (OPA) policies
  • Terraform modules: Infrastructure as Code artifacts
  • Git repository snapshots: Source code archives

5. Machine Learning Models

ML models and datasets are increasingly stored in OCI registries:

  • Model weights: Trained neural network parameters
  • Model metadata: Training metrics, hyperparameters, and lineage
  • Dataset snapshots: Versioned training and validation data
  • Inference runtimes: Containerized model serving applications

6. WebAssembly Modules

WASM modules can be distributed through OCI registries:

  • Compiled WASM binaries: Portable executable modules
  • WASI components: WebAssembly System Interface modules
  • Module metadata: Dependencies and interface specifications

Supported Technologies and Standards

OCI repositories integrate with a rich ecosystem of technologies:

Core OCI Specifications

  1. OCI Image Specification: Defines the format of container images
  2. OCI Distribution Specification: Defines the API for registry interactions
  3. OCI Runtime Specification: Defines how to run containers (used by runtimes, not registries directly)

Content Types and Media Types

OCI repositories support various media types through the manifest format:

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "digest": "sha256:abc123...",
    "size": 1234
  },
  "layers": [
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:def456...",
      "size": 5678
    }
  ]
}

Registry Implementations

Popular OCI-compliant registry implementations include:

  • Docker Hub: The default public registry for Docker
  • GitHub Container Registry (GHCR): Integrated with GitHub packages
  • Amazon Elastic Container Registry (ECR): AWS-managed registry service
  • Google Artifact Registry: Google Cloud’s artifact management solution
  • Azure Container Registry (ACR): Microsoft Azure’s container registry
  • Harbor: Open-source registry with enterprise features
  • Quay.io: Red Hat’s container registry service
  • JFrog Artifactory: Universal artifact repository
  • GitLab Container Registry: Integrated with GitLab CI/CD
  • Distribution (formerly Docker Registry): The reference implementation

Security Mechanisms in OCI Repositories

Security is paramount in container image distribution. OCI repositories support multiple security layers:

1. Authentication and Authorization

Authentication Methods:

  • Basic authentication: Username and password (over HTTPS)
  • Token-based authentication: JWT tokens for API access
  • OAuth 2.0: Delegated authorization flows
  • Service accounts: Machine-to-machine authentication
  • Mutual TLS (mTLS): Certificate-based authentication

Authorization Models:

  • Role-Based Access Control (RBAC): Permissions based on user roles
  • Repository-level permissions: Read, write, and delete access per repository
  • Namespace isolation: Multi-tenancy with isolated namespaces
  • Fine-grained policies: Attribute-based access control (ABAC)

2. Content Trust and Image Signing

Docker Content Trust (DCT):

  • Uses The Update Framework (TUF) for secure image distribution
  • Provides publisher verification and freshness guarantees
  • Cryptographic signatures verify image authenticity

Cosign and Sigstore:

# Sign an image with Cosign
cosign sign registry.example.com/myapp:v1.0

# Verify a signed image
cosign verify registry.example.com/myapp:v1.0

Notary v2:

  • Next-generation implementation of content trust
  • Supports multiple signature formats and verification policies
  • Integrates with OCI artifact storage

3. Vulnerability Scanning

OCI repositories integrate with vulnerability scanners:

  • Trivy: Comprehensive vulnerability scanner for containers
  • Grype: Fast vulnerability scanner by Anchore
  • Clair: Static analysis for known vulnerabilities
  • Snyk: Commercial vulnerability scanning platform

Scanning workflows:

# Scan image with Trivy
trivy image registry.example.com/myapp:v1.0

# Scan and block on critical vulnerabilities
trivy image --severity CRITICAL,HIGH --exit-code 1 myapp:v1.0

4. Admission Control

Registries integrate with Kubernetes admission controllers:

  • Kyverno: Policy engine for Kubernetes that can verify image signatures
  • OPA Gatekeeper: General-purpose policy enforcement
  • Ratify: Supply chain verification for Kubernetes

Example Kyverno policy:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signature
spec:
  validationFailureAction: enforce
  rules:
  - name: verify-signature
    match:
      resources:
        kinds:
        - Pod
    verifyImages:
    - imageReferences:
      - "registry.example.com/*"
      attestors:
      - count: 1
        entries:
        - keys:
            publicKeys: |-
              -----BEGIN PUBLIC KEY-----
              ...
              -----END PUBLIC KEY-----              

5. Network Security

  • TLS encryption: All communications over HTTPS
  • Private networks: Registry access via VPC or private endpoints
  • IP allowlisting: Restrict access to specific IP ranges
  • Rate limiting: Prevent abuse and DDoS attacks

6. Image Immutability

  • Digest-based references: Ensures exact image version is deployed
  • Tag immutability: Prevents tag overwriting in production
  • Retention policies: Automatic cleanup of old or unused images

Useful Clients and Tools for OCI Repositories

Container Runtime Clients

Docker CLI:

# Pull an image
docker pull registry.example.com/myapp:v1.0

# Push an image
docker push registry.example.com/myapp:v1.0

# Inspect image manifest
docker manifest inspect registry.example.com/myapp:v1.0

Podman:

# Podman uses the same commands as Docker
podman pull registry.example.com/myapp:v1.0
podman push registry.example.com/myapp:v1.0

containerd (nerdctl):

# Native containerd CLI
nerdctl pull registry.example.com/myapp:v1.0
nerdctl push registry.example.com/myapp:v1.0

OCI Artifact Clients

ORAS (OCI Registry As Storage):

# Push any artifact
oras push registry.example.com/myartifact:v1.0 \
  --artifact-type application/vnd.example.config \
  config.yaml:application/yaml

# Pull artifact
oras pull registry.example.com/myartifact:v1.0

Helm (OCI Support):

# Push Helm chart
helm push mychart-1.0.0.tgz oci://registry.example.com/charts

# Pull and install
helm install myapp oci://registry.example.com/charts/mychart --version 1.0.0

Registry Management Tools

Crane (part of go-containerregistry):

# Copy image between registries
crane copy source.io/image:tag dest.io/image:tag

# List tags
crane ls registry.example.com/myapp

# Get digest
crane digest registry.example.com/myapp:v1.0

# Delete image
crane delete registry.example.com/myapp:v1.0

Skopeo:

# Copy image
skopeo copy docker://source.io/image:tag docker://dest.io/image:tag

# Inspect remote image without pulling
skopeo inspect docker://registry.example.com/myapp:v1.0

# Delete image
skopeo delete docker://registry.example.com/myapp:v1.0

regctl (from regclient):

# List repositories
regctl repo ls registry.example.com

# List tags
regctl tag ls registry.example.com/myapp

# Copy image
regctl image copy source.io/image:tag dest.io/image:tag

Security and Verification Tools

Cosign:

# Generate key pair
cosign generate-key-pair

# Sign image
cosign sign --key cosign.key registry.example.com/myapp:v1.0

# Verify signature
cosign verify --key cosign.pub registry.example.com/myapp:v1.0

# Attach SBOM
cosign attach sbom --sbom sbom.json registry.example.com/myapp:v1.0

Trivy:

# Scan for vulnerabilities
trivy image registry.example.com/myapp:v1.0

# Generate SBOM
trivy image --format cyclonedx registry.example.com/myapp:v1.0

Required Capabilities for Client Interaction

OCI registries must support specific API endpoints to enable client interactions:

Core API Endpoints

1. Version Check:

GET /v2/

Returns API version and confirms registry availability.

2. Authentication:

GET /v2/
Response: 401 with WWW-Authenticate header

Initiates authentication flow.

3. Pushing Blobs:

POST /v2/<name>/blobs/uploads/
PUT /v2/<name>/blobs/uploads/<uuid>

Uploads image layers and configuration.

4. Pushing Manifests:

PUT /v2/<name>/manifests/<reference>

Uploads image manifest.

5. Pulling Manifests:

GET /v2/<name>/manifests/<reference>

Downloads image manifest.

6. Pulling Blobs:

GET /v2/<name>/blobs/<digest>

Downloads image layers.

7. Deleting Objects:

DELETE /v2/<name>/manifests/<reference>
DELETE /v2/<name>/blobs/<digest>

Removes manifests and blobs.

8. Listing Tags:

GET /v2/<name>/tags/list

Returns all tags for a repository.

Extended Capabilities

Content Discovery:

GET /v2/_catalog

Lists all repositories in the registry.

Blob Mounting:

POST /v2/<name>/blobs/uploads/?mount=<digest>&from=<repository>

Efficiently copies blobs between repositories.

Referrers API:

GET /v2/<name>/referrers/<digest>

Discovers artifacts that reference a specific manifest (signatures, SBOMs).

Chunked Upload:

PATCH /v2/<name>/blobs/uploads/<uuid>

Supports resumable uploads for large layers.

Using Labels in CI/CD Pipelines

Labels (also called annotations in OCI manifests) are key-value pairs that provide metadata about images and artifacts. They enable powerful automation and policy enforcement in CI/CD pipelines.

Standard Label Schemas

OCI Image Annotations:

LABEL org.opencontainers.image.created="2026-01-26T21:00:00Z"
LABEL org.opencontainers.image.authors="team@example.com"
LABEL org.opencontainers.image.url="https://example.com/myapp"
LABEL org.opencontainers.image.documentation="https://docs.example.com"
LABEL org.opencontainers.image.source="https://github.com/example/myapp"
LABEL org.opencontainers.image.version="1.0.0"
LABEL org.opencontainers.image.revision="abc123def"
LABEL org.opencontainers.image.vendor="Example Corp"
LABEL org.opencontainers.image.licenses="Apache-2.0"
LABEL org.opencontainers.image.title="My Application"
LABEL org.opencontainers.image.description="A sample application"

CI/CD Integration Patterns

1. Build Metadata Injection:

# GitHub Actions example
- name: Build and push
  uses: docker/build-push-action@v5
  with:
    push: true
    tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
    labels: |
      org.opencontainers.image.created=${{ steps.date.outputs.date }}
      org.opencontainers.image.revision=${{ github.sha }}
      org.opencontainers.image.source=${{ github.repositoryUrl }}
      ci.build-number=${{ github.run_number }}
      ci.build-url=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}      

2. Environment-Based Routing:

# Tag images with environment labels
docker build -t myapp:v1.0 --label environment=production .
docker build -t myapp:v1.0-staging --label environment=staging .

# Query by label (conceptually, requires registry API support)
# Deploy only production-labeled images to production cluster

3. Promotion Workflows:

# GitLab CI example
promote-to-production:
  stage: promote
  script:
    # Copy image and add production label
    - crane copy $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:production
    - |
      crane mutate $CI_REGISTRY_IMAGE:production \
        --label promoted-by=$GITLAB_USER_LOGIN \
        --label promoted-at=$(date -u +%Y-%m-%dT%H:%M:%SZ) \
        --label environment=production      

4. Compliance and Auditing:

# Include audit trail in labels
LABEL audit.scanned-by="trivy"
LABEL audit.scan-date="2026-01-26"
LABEL audit.vulnerability-count="0"
LABEL audit.approved-by="security-team"
LABEL compliance.pci-dss="compliant"
LABEL compliance.soc2="compliant"

5. Automated Cleanup Policies:

# Delete images older than 30 days without production label
# (Pseudo-code for cleanup script)
for image in $(list_images); do
  if [[ $(get_label $image "environment") != "production" ]] && \
     [[ $(get_age $image) -gt 30 ]]; then
    delete_image $image
  fi
done

6. Deployment Configuration:

# ArgoCD/Flux can select images by labels
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: app
    image: registry.example.com/myapp
    imagePullPolicy: IfNotPresent
  # Image selection based on labels (via admission controller)
  annotations:
    image-policy.kubernetes.io/match: |
      environment=production,
      audit.approved-by=security-team      

Frequently Asked Questions (FAQ)

How are OCI repositories traversed?

OCI repositories can be traversed using several methods:

1. Catalog API: The catalog endpoint lists all repositories:

curl -X GET https://registry.example.com/v2/_catalog

Response:

{
  "repositories": ["myapp", "mydb", "utils/helper"]
}

2. Tags List API: For each repository, list available tags:

curl -X GET https://registry.example.com/v2/myapp/tags/list

Response:

{
  "name": "myapp",
  "tags": ["latest", "v1.0.0", "v1.1.0", "dev"]
}

3. Manifest Inspection: Retrieve the manifest for a specific tag or digest:

curl -X GET \
  -H "Accept: application/vnd.oci.image.manifest.v1+json" \
  https://registry.example.com/v2/myapp/manifests/v1.0.0

4. Referrers Discovery: Find artifacts that reference a specific image (signatures, SBOMs):

curl -X GET \
  https://registry.example.com/v2/myapp/referrers/sha256:abc123...

5. Using Client Tools:

# List repositories with crane
crane catalog registry.example.com

# List tags
crane ls registry.example.com/myapp

# Inspect manifest
crane manifest registry.example.com/myapp:v1.0.0

How are objects stored in OCI repositories?

OCI repositories use a content-addressable storage model:

1. Blob Storage:

  • Each layer and configuration is stored as a blob
  • Blobs are identified by their SHA-256 digest
  • Identical blobs are deduplicated (stored once, referenced many times)
  • Storage path: /v2/<name>/blobs/sha256:<digest>

2. Manifest Storage:

  • Manifests describe the composition of images and artifacts
  • Stored at /v2/<name>/manifests/<reference>
  • Can be referenced by tag (mutable) or digest (immutable)

3. Layer Structure:

Registry Storage
├── blobs/
│   ├── sha256/
│   │   ├── abc123... (base layer)
│   │   ├── def456... (app layer)
│   │   └── ghi789... (config)
├── manifests/
│   └── myapp/
│       ├── v1.0.0 → sha256:xyz...
│       └── latest → sha256:xyz...

4. Deduplication: When multiple images share layers, only one copy is stored:

Image A: [layer1, layer2, layer3]
Image B: [layer1, layer4, layer5]
Stored:  [layer1, layer2, layer3, layer4, layer5]

5. Garbage Collection: Unused blobs (not referenced by any manifest) are periodically removed to reclaim space.

What are the interrelations between objects?

Objects in OCI repositories form a directed acyclic graph (DAG):

1. Image Index → Manifests: An image index (multi-platform image) points to multiple platform-specific manifests:

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.index.v1+json",
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:amd64_manifest...",
      "platform": {"architecture": "amd64", "os": "linux"}
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:arm64_manifest...",
      "platform": {"architecture": "arm64", "os": "linux"}
    }
  ]
}

2. Manifest → Config + Layers: An image manifest references a configuration blob and multiple layer blobs:

{
  "config": {
    "digest": "sha256:config_digest..."
  },
  "layers": [
    {"digest": "sha256:layer1_digest..."},
    {"digest": "sha256:layer2_digest..."}
  ]
}

3. Artifact → Subject (Referrers): Signatures and SBOMs reference their subject artifact:

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "subject": {
    "mediaType": "application/vnd.oci.image.manifest.v1+json",
    "digest": "sha256:subject_image_digest..."
  },
  "layers": [
    {"digest": "sha256:signature_blob..."}
  ]
}

4. Dependency Graph:

Tag (v1.0.0)
  └─> Manifest (sha256:abc...)
        ├─> Config Blob (sha256:def...)
        ├─> Layer 1 (sha256:ghi...)
        ├─> Layer 2 (sha256:jkl...)
        └─> Layer 3 (sha256:mno...)
  
Signature
  └─> Manifest (sha256:sig...)
        ├─> Subject: Manifest (sha256:abc...)
        └─> Signature Blob (sha256:pqr...)

5. Shared References: Multiple tags and manifests can reference the same blobs, enabling efficient storage and transfer.

How do you host an OCI repository on GitHub?

GitHub Container Registry (GHCR) is GitHub’s OCI-compliant registry service:

1. Enable GHCR:

  • Navigate to your repository or organization settings
  • Enable GitHub Packages

2. Authenticate:

# Create a personal access token (PAT) with `write:packages` scope
# At https://github.com/settings/tokens

# Login to GHCR
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin

3. Build and Tag Image:

# Tag with GHCR naming convention
docker build -t ghcr.io/USERNAME/REPO/IMAGE:TAG .

4. Push to GHCR:

docker push ghcr.io/USERNAME/REPO/IMAGE:TAG

5. Configure Visibility:

  • In GitHub, navigate to Packages
  • Select your package
  • Change visibility (Public/Private/Internal)

6. GitHub Actions Integration:

name: Build and Push to GHCR

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: |
            ghcr.io/${{ github.repository }}:${{ github.sha }}
            ghcr.io/${{ github.repository }}:latest            
          labels: |
            org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
            org.opencontainers.image.revision=${{ github.sha }}            

7. Pull Images:

# Public images (no authentication needed)
docker pull ghcr.io/USERNAME/REPO/IMAGE:TAG

# Private images (requires authentication)
docker login ghcr.io
docker pull ghcr.io/USERNAME/REPO/IMAGE:TAG

8. Best Practices:

  • Use github.token for CI/CD workflows (automatically scoped)
  • Link packages to repositories for better organization
  • Configure package retention policies to manage storage
  • Use semantic versioning for tags
  • Implement automated scanning with GitHub Security features

How do you host an OCI repository on AWS?

Amazon Elastic Container Registry (ECR) provides managed OCI registry hosting:

1. Create ECR Repository:

# Using AWS CLI
aws ecr create-repository \
  --repository-name myapp \
  --region us-east-1 \
  --image-scanning-configuration scanOnPush=true \
  --encryption-configuration encryptionType=KMS

2. Authenticate:

# Get authentication token and login
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin \
  ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com

3. Build and Tag Image:

# Tag with ECR naming convention
docker build -t ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/myapp:v1.0 .

4. Push to ECR:

docker push ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/myapp:v1.0

5. Configure Repository Policies:

# Set lifecycle policy to clean up old images
aws ecr put-lifecycle-policy \
  --repository-name myapp \
  --lifecycle-policy-text file://policy.json

Example lifecycle policy:

{
  "rules": [
    {
      "rulePriority": 1,
      "description": "Expire untagged images older than 7 days",
      "selection": {
        "tagStatus": "untagged",
        "countType": "sinceImagePushed",
        "countUnit": "days",
        "countNumber": 7
      },
      "action": {
        "type": "expire"
      }
    },
    {
      "rulePriority": 2,
      "description": "Keep only 10 most recent images",
      "selection": {
        "tagStatus": "any",
        "countType": "imageCountMoreThan",
        "countNumber": 10
      },
      "action": {
        "type": "expire"
      }
    }
  ]
}

6. Configure IAM Permissions:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecr:GetAuthorizationToken",
        "ecr:BatchCheckLayerAvailability",
        "ecr:GetDownloadUrlForLayer",
        "ecr:BatchGetImage"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ecr:PutImage",
        "ecr:InitiateLayerUpload",
        "ecr:UploadLayerPart",
        "ecr:CompleteLayerUpload"
      ],
      "Resource": "arn:aws:ecr:us-east-1:ACCOUNT_ID:repository/myapp"
    }
  ]
}

7. Enable Security Scanning:

# Enable enhanced scanning with Inspector
aws ecr put-registry-scanning-configuration \
  --scan-type ENHANCED \
  --rules '[{"repositoryFilters":[{"filter":"*","filterType":"WILDCARD"}],"scanFrequency":"CONTINUOUS_SCAN"}]'

8. CI/CD Integration (GitHub Actions):

name: Deploy to ECR

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1
      
      - name: Login to ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2
      
      - name: Build, tag, and push
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: myapp
          IMAGE_TAG: ${{ github.sha }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \
                     $ECR_REGISTRY/$ECR_REPOSITORY:latest
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest          

9. Cross-Region Replication:

# Enable replication to multiple regions
aws ecr put-replication-configuration \
  --replication-configuration file://replication.json

Example replication configuration:

{
  "rules": [
    {
      "destinations": [
        {
          "region": "us-west-2",
          "registryId": "ACCOUNT_ID"
        },
        {
          "region": "eu-west-1",
          "registryId": "ACCOUNT_ID"
        }
      ]
    }
  ]
}

10. Pull from EKS: ECR integrates seamlessly with Amazon EKS. Pods can pull images using IAM roles:

apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  serviceAccountName: myapp-sa  # With IAM role for ECR access
  containers:
  - name: app
    image: ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/myapp:v1.0

Conclusion

OCI repositories have evolved far beyond simple container image storage to become versatile artifact management platforms. They support a wide range of content types, integrate with comprehensive security mechanisms, and provide robust APIs for client interaction. Understanding these capabilities enables teams to:

  • Standardize artifact storage: Use a single platform for all deployment artifacts
  • Enhance security: Leverage signing, scanning, and admission control
  • Automate workflows: Integrate with CI/CD pipelines using labels and metadata
  • Improve efficiency: Benefit from content deduplication and caching
  • Ensure compliance: Track provenance and maintain audit trails

Whether you’re using GitHub Container Registry for open-source projects, AWS ECR for cloud-native applications, or Harbor for on-premises deployments, the OCI Distribution Specification ensures consistent behavior and interoperability across platforms. By mastering OCI repository capabilities, development teams can build more secure, efficient, and automated software delivery pipelines.

Resources