Leveraging Generic Artifact Stores with OCI Images and ORAS

James Walker
Minute Read

OCI registries are the default distribution mechanism for container images. Services such as Docker Hub provide an OCI-compliant registry that lets you push and pull images with compatible clients like the Docker CLI.

Modern cloud-native systems aren't just container images, though. An application deployment will often depend on other artifacts, such as a Helm chart or a data volume, before it can be completed.

OCI registries are evolving to meet these requirements. The OCI Registry As Storage (ORAS) project provides a mechanism for storing and retrieving arbitrary data types using existing OCI registries. This allows you to colocate your container images, Helm charts, and other deployment artifacts in a single repository that you manage with familiar push and pull commands.

This article explains the motivation behind ORAS and the challenges it solves. You'll also see how to get started adding arbitrary data to a registry using the ORAS CLI.

What's an OCI Registry?

An OCI registry is an implementation of a container image storage service that supports the OCI Distribution Specification. This spec defines the features and behavior expected of image registries, so they're interoperable across the container ecosystem. An image in an OCI registry can be consumed by any compatible container client, such as Docker, Podman, or Kubernetes.

The most well-known OCI registry is Docker Hub. This public service formed the basis of the specification and remains the largest source of container images. However, many other OCI registries are also available, including GitHub Container Registry, Amazon ECR, and Azure Container Registry.

What's an OCI Artifact?

An "artifact" in OCI terms is a piece of content stored in a registry. Most artifacts created so far have been container images because registries didn't originally support other content types. Many different types of artifacts are now known to the ecosystem, including Helm charts, SBOMs, and vulnerability reports. Generic content types can exist as artifacts, too.

OCI registries aren't restricted to container images anymore; they're abstract artifact stores that can distribute any kind of data relevant to your application. Before the artifact standard was developed, some teams were already using registries in a similar way by placing arbitrary files in utility container images and pushing those images to a registry. Artifacts mean it's no longer necessary to wrap all content in an image before it's pushed to OCI storage.

What Is ORAS?

ORAS provides a set of tools for storing and managing OCI artifacts in registries. The project publishes a command line interface (CLI) that can push and pull your content, alongside official client libraries for developers integrating OCI artifact support into their own applications.

The ORAS project focuses on non-image artifacts. Commands like docker push and docker pull already offer a mature user experience for working with images. Although you could push an image with the ORAS CLI, it would require more arguments and configuration than a regular docker push my-image:latest command. Other tools like Helm also offer wrappers that simplify working with their own artifact types. The ORAS CLI is mainly intended for arbitrary files with generic content types.

ORAS Use Cases

ORAS is suitable for any situation where you need to store additional artifacts alongside your container images, either because they're required for deployment or as useful references for consumers. The following sections highlight three possible scenarios.

Store Helm Charts alongside Your Images

Apps are often deployed to Kubernetes using Helm charts that allow all their components to be created in a repeatable manner. Charts used to be stored in dedicated Helm repositories, but ORAS lets you push them to the same OCI registry that stores your container images.

Keep Policy Definitions with Your Artifacts

Systems such as Open Policy Agent (OPA) let you set up configuration and security policies for your environment. However, end users still need to discover and apply the policies, creating a friction point in the deployment experience. You can use ORAS to publish your OPA bundles to your registry. Users can pull your container images and accompanying policies from a single location.

Provide Up-To-Date SBOMs with Your Application

Supply chain security is topical throughout software development and DevOps. Software bill of materials (SBOM) artifacts list every third-party package that a system depends on, giving you visibility into its dependency tree. With ORAS, you can upload your SBOMs to the same registry as your container images. Future tools will be able to automatically detect the presence of assets like SBOMs in your registry, allowing relevant safety information to be shown at the point an image is pulled.

Examples: ORAS in Action

Now that you understand the use cases for ORAS, you can put it into action by creating some simple artifacts and pushing them to a registry. The steps below show how to use ORAS and OCI registries to store your application's images, Helm charts, and SBOM files.

Prerequisites

First, install the ORAS CLI by following the instructions in the documentation. Binaries are available for Windows, macOS, and Linux.

Next, create or connect to an OCI registry that supports artifacts. Check whether your preferred provider is compatible by visiting the ORAS documentation.

You can start your own registry by running the CNCF Distribution reference registry in a Docker container. First, create a htpasswd file containing the credentials that will secure the registry:

htpasswd -cB -b auth.htpasswd registry-user registry-password

Next, run the following command to launch your registry server on port 5000:

docker run -d -p 5000:5000 \
    -v $PWD/auth.htpasswd:/etc/docker/registry/auth.htpasswd \
    -e REGISTRY_AUTH="{htpasswd: {realm: localhost, path: /etc/docker/registry/auth.htpasswd}}" \
    registry:latest

Authenticating to Your Registry

The fundamental ORAS commands are similar to ones you may already be familiar with from the docker CLI. ORAS also reuses your Docker auth settings—if you've already logged into registries with docker login, ORAS will detect your credentials automatically. It reads and writes the same ~/.docker/config.json file without introducing any conflicts.

You can log in to a new registry for the first time with the oras login command. Use this to log in to the registry you created above:

oras login -u registry-user -p registry-password localhost:5000

You can optionally instruct the command to read your password from standard input using the --password-stdin flag:

cat password.txt | oras login -u registry-user --password-stdin localhost:5000

Pushing an Image

Next, use the ORAS CLI to list the contents of your registry:

oras repo ls localhost:5000

As you can see, there's nothing there! Time to add some content.

Run the following command to pull Docker's standard "hello world" image:

docker pull hello-world:latest

Next, tag the following image so you can push it to your registry:

docker tag hello-world:latest localhost:5000/hello:latest

Push the new tag:

docker push localhost:5000/hello:latest
The push refers to repository [localhost:5000/hello]
e07ee1baac5f: Pushed
latest: digest: sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4 size: 525

With the push successful, use ORAS to list the contents of your registry again:

oras repo ls localhost:5000
hello

The image should show up as expected. You can get the available tags with the following command:

oras repo tags localhost:5000/hello
latest

Pushing a Helm Chart

Next, use the helm create command to scaffold a basic Helm chart in your working directory:

helm create my-chart
Creating my-chart

Helm will populate an initial set of chart templates into the my-chart subdirectory. The chart's details aren't relevant to this tutorial.

Package the chart as an archive ready for distribution:

helm package my-chart
Successfully packaged chart and saved it to: /my-chart-0.1.0.tgz

Next, run the helm push command to add the chart to your registry:

helm push my-chart-0.1.0.tgz oci://localhost:5000/my-chart
Pushed: localhost:5000/my-chart/my-chart:0.1.0
Digest: sha256:a9ddf3d4c6353528a536b7c7c5893a57f59c6ba9fd9bd7a220d47334c22ca2fb

The push command takes the path to the chart archive as its first argument. The second argument is a storage URI. The oci scheme indicates that an OCI registry is being targeted instead of a Helm repository. Specify your registry's URL and the name of the repo to create. Helm automatically tags the pushed content with the version code defined by your chart.

You can now use the ORAS CLI again to confirm the new content has been added:

oras repo ls localhost:5000
hello
my-chart/my-chart

Two kinds of artifacts are now present, each pushed by a different tool: a Helm chart and an OCI image added by Docker.

Pushing a Generic Artifact

You're now going to add a generic artifact: an SBOM in CycloneDX JSON format. This is a standalone JSON file, but it makes sense to distribute it alongside the application's image and Helm chart. For the purposes of this tutorial, you can download one of the sample SBOMs from the CycloneDX project:

curl https://raw.githubusercontent.com/CycloneDX/bom-examples/master/SBOM/laravel-7.12.0/bom.1.2.json -o sbom.json

You can push this SBOM to your registry with the following ORAS CLI command:

oras push localhost:5000/hello/sbom:v1 \
    sbom.json:application/json \
    --artifact-type application/vnd.unknown.config.v1+json
Uploading e2f7fc1cc20a sbom.json
Uploaded  e2f7fc1cc20a sbom.json
Pushed localhost:5000/hello/sbom:v1
Digest: sha256:669c89865c3b0edef8c7bf5e02dea6af34cc63772a36f203300a2e633139d46f

There are three important arguments to note:

  1. Registry path and tag: The first argument defines the registry URL, repository path, and tag to upload the content to.
  2. Local file path and content type: The second argument provides the path to the file to upload and its content (MIME) type, separated by a colon (:).
  3. The --artifact-type flag: The artifact type signals the kind of content that's being published. There are specific types for well-known items in the container ecosystem, such as OCI images and Helm charts. You can use application/vnd.unknown.config.v1+json for generic content.

Listing your registry's content once more will show that the SBOM has been uploaded:

oras repo list localhost:5000
hello
hello/sbom
my-chart/my-chart

Pulling from the Registry

Time to retrieve your stored content! You can access the Docker image and Helm chart using the standard pull commands of the respective tools:

docker pull localhost:5000/hello:latest
helm pull oci://localhost:5000/my-chart/my-chart:0.1.0

Change to a new directory to avoid confusion with the file you uploaded earlier, then run oras pull, specifying the registry URL, repository path, and tag to retrieve the SBOM:

mkdir pull-demo
cd pull-demo
cat sbom.json
cat: sbom.json: No such file or directory

Now pull the file from the registry:

oras pull localhost:5000/hello/sbom:v1
Downloading e2f7fc1cc20a sbom.json
Downloaded  e2f7fc1cc20a sbom.json
Pulled localhost:5000/hello/sbom:v1
Digest: sha256:f2aeac528eee1b072126a11f640bfb2721d06ac6750572c696c88b603598c806

The file should now exist in your working directory:

cat sbom.json
{
    "$schema": "http://cyclonedx.org/schema/bom-1.2a.schema.json",
    "bomFormat": "CycloneDX",
    "specVersion": "1.2",
    "version": 1,
    ...

You've successfully stored and retrieved generic OCI artifacts with an OCI registry.

Conclusion

ORAS broadens the scope of OCI registries to include all software artifacts instead of only container images. As the OCI artifact spec matures, you'll be able to use a single distribution platform for images, Helm charts, storage volumes, config files, SBOMs, and any other data that relates to your apps.

ORAS sets the future direction for interoperability around artifacts. Unified storage will enable powerful new tools, such as a future CLI that lets you input an app's registry, view the CVE alerts in its SBOM, and then deploy the Helm chart and any Open Policy Agent bundles in one step.

ORAS solves several challenges around modern application deployment, but other solutions are also invaluable for setting up, scaling, and securing your container infrastructure. Loft provides a Kubernetes development platform that offers self-service virtual clusters, multitenancy, and collaborative access management. Boost developer velocity by quickly launching isolated Kubernetes environments that are ready to deploy your images, charts, and other assets from your OCI registries.

Sign up for our newsletter

Be the first to know about new features, announcements and industry insights.