OCI #10 – Docker Container Registry in Oracle Cloud

This recipe shows how to work with Oracle Cloud Infrastructure Registry (Docker Image Registry in Oracle Cloud).

Before you start, you should install and configure Oracle Cloud Infrastructure CLI. See: OCI Setup recipe, if needed.


Everything around production-grade Linux containers at mass scale has really begun with this short demo back in 2013. Linux container engines make use of Linux kernel features (cgroups, namespaces) to isolate applications executed inside logical entities called containers, which are built from multi-layered templates called images. You can watch this comprehensive introduction video. Docker is the most popular Linux container engine, however, there are also a bit less mature alternatives like CNCF-incubating rkt or containerd.

Container Image Registry

In order to leverage containers in production you need to store somewhere the Docker images for your applications. Oracle Cloud Infrastructure comes with Oracle Cloud Infrastructure Registry (OCIR), an Oracle-managed registry, where you can store your Docker images as private and public repositories. A single Registry repository can be thought of as a set of related, tagged Docker image versions for a single (micro)service. Tags are used to denote particular versions of a (micro)service. In other words you keep a separate Docker Registry repository for all versions of each individual (micro)service. An orchestration engine (for example Kubernetes) would then pull images from the registry and run new containers on various worker nodes.

Access policies

A user can interact with OCIR, if there is a correct IAM policy defined for the IAM group the user belongs to. This policy allows a group of users to create and delete repositories, push and pull images and change the visibility of a repository (between public and private):

allow group groupName to manage repos in tenancy where target.repo.name = /projectName-*/

The where clause, at the end of the policy statement, says that the policy refers only to these repositories whose names start with projectName-. Why would we need it? Each Cloud Account comes with a single Docker image registry that, by default, can store up to 500 repositories. In a multi-project environment, you usually need to control user access to selected repositories depending on the project that owns given images. In this case, you can use IAM policies that rely on project prefixes. When naming images, you can prefix each image. When you push an image into registry, it is resembled as repository with the same name. As a result, you can limit access rights for different IAM groups using IAM policies with repository name filters.


You can reuse an OCI CLI script I’ve prepared. First clone the Git repository:

git clone https://github.com/mtjakobczyk/blog-code.git
cd blog-code/oci-10

You can simply customize and execute this script as OCI tenancy or compartment administrator:

# oci/create-ocir-policy.sh 1/1

# Add a new policy statement to let group member manage OCIR repositories with a specific naming pattern
OCI_POLICY_MANAGE="allow group $OCI_GROUP to manage repos in tenancy where target.repo.name = /$OCI_PROJECT_PREFIX-*/"
oci iam policy create -c $OCI_POLICY_COMPARTMENT_OCID --name $OCI_POLICY_NAME --description "$OCI_POLICY_DESC" --statements "[ \"$OCI_POLICY_MANAGE\" ]"

You can find the entire script here.

There is one thing, I need to mention at this stage. The policy we’ve just added let’s the group members push and pull images, which is their core task. However, they won’t be able to list the repositories neither in OCI Console nor using API.  Actually, if you carefully think about the automation you would most probably involve, you may not need such capability. Yet, if you still prefer to allow the users to browse through the list of all OCIR repositories that are available in the tenancy’s OCIR, please add the following statement:

allow group groupName to inspect repos in tenancy where request.operation='ListDockerRepositories'

Generate Authentication Token

OCI IAM users can interact with OCIR using Docker v2 API and Docker client. The authentication is token-based. Before a user performs docker login against OCIR, he has to generate an authentication token for the corresponding IAM user. Let me show you two ways how to do it:

I. Done by the user in OCI Console – ad-hoc self-service approach:

  1. Sign in to OCI Console as the IAM user you would like to generate an authentication token for
  2. Go to User Settings
  3. You should see user details for this user. Go to Resources ➟ Auth Tokens and click Generate Token
  4. Note down the newly generated token, because you will never be able to display it again in OCI Console.

II. CLI-driven – automating authentication token creation (especially for another user):

  1. Identify the OCID of the IAM user for which you would like to generate an authentication token
  2. Execute the following CLI command:
    oci iam auth-token create --user-id $IAM_USER_OCID --description Token-1 | grep token
        "token": "XIaTLD9uP_(rX9W3]r#w",
  3. Note down the newly generated token, because you will see it only once.

Please note a single IAM user can have up to two authentication tokens at any given time.

Pushing a Docker image into OCIR

In the previous two sections we added a required policy and generated an authentication token for an IAM user. Now, we are ready to push a Docker image to OCIR.

In this example, we will build on our local machine a Docker image that encapsulates a simple Node.js application and push it into OCIR. If you cloned the Git repository I linked earlier in this post, make sure you are in this folder first:

cd blog-code/oci-10

Now, execute the following commands:

cd app
docker build -t $IMAGE_NAME:$IMAGE_TAG .
docker login -u $OCI_TENANCY/$OCI_USER $OCIR_REGION.ocir.io
### You will be prompted for the auth token here

You can find the entire script here.

The code above will:

  • build a Docker image with simple Node.js application
  • tag the new image using the format required by OCID
  • login to a remote registry (OCIR)
  • push the image to OCIR
Sending build context to Docker daemon 3.072 kB
Step 1/4 : FROM node:10.13-alpine
Trying to pull repository docker.io/library/node ... 
10.13-alpine: Pulling from docker.io/library/node
4fe2ade4980c: Pull complete 
e4ac5f64a73e: Pull complete 
f62e97d98767: Pull complete 
Digest: sha256:5ba2248f02abf173f0fb2bd6f84fca7f3616496c50c9333cdd362314ec2970d9
Status: Downloaded newer image for docker.io/node:10.13-alpine
 ---> e35872f034fd
Step 2/4 : ADD app.js .
 ---> e603137d5ad2
Removing intermediate container c6eac4b1d54b
Step 3/4 : EXPOSE 8080
 ---> Running in 5626417a29fc
 ---> 6d7cd9fbe57b
Removing intermediate container 5626417a29fc
Step 4/4 : CMD node app.js
 ---> Running in aa8c48327a61
 ---> 106ddc2d93a6
Removing intermediate container aa8c48327a61
Successfully built 106ddc2d93a6
Login Succeeded
The push refers to a repository [fra.ocir.io/▋▋▋▋▋▋/p-oraas-simple-api]
e8f3411efc34: Pushed 
f87e587403a6: Pushed 
819d7ee3ee24: Pushed 
df64d3292fd6: Pushed 
1.0: digest: sha256:1525924e4e79f5cc5d7a67a755343cac0568ce40f773badc8981d08d555f9b1f size: 1158

You should be able to see the newly created repository in OCIR. Just log in as an administrator or any other user that belongs to the group to which you’ve granted ListDockerRepositories operation access.


You can find the code I presented in this chapter here.