This cheat sheet is about, how to configure a project in an IBM Cloud Red Hat OpenShift to access the IBM Cloud Container Registry. We use an image pull secret to access container images from IBM Cloud Container Registries. The cheat sheet combines different steps, which are available in the IBM Cloud documentation you find here.
We configure a created project in OpenShift to access two different IBM Cloud Container Registries.
- The first IBM Cloud Container Registry is a part of the
IBM Cloud Account
where we instantiated the IBM Cloud Red Hat OpenShift cluster. Let us call thisIBM Cloud Account ONE
. - The second IBM Cloud Container Registry is a part of another
IBM Cloud Account
calledIBM Cloud Account TWO
. This configuration works like to the configuration for external private registries.
The IBM Cloud Red Hat OpenShift cluster is a part of IBM Cloud Account ONE
.
The image below shows a simplified architecture overview:

Note: The cheat sheet references to source code, which is available in that example GitHub project. In case you want to follow the steps, you can clone the GitHub project to your local computer.
The blog post is organized in five following sections:
- Setup the
IBM Cloud Container Registry
ofIBM Cloud Account TWO
- Build and push the container image to the IBM Cloud Container Registry of
IBM Cloud Account TWO
- Configure the OpenShift project to access the
IBM Cloud Container Registry
ofIBM Cloud Account ONE
- Configure the OpenShift project to access the
IBM Cloud Container Registry
ofIBM Cloud Account TWO
- Deploy the container image to the OpenShift project
1. Setup the IBM Cloud Container Registry
of IBM Cloud Account TWO
¶
On our local computer we use the IBM Cloud CLI and the IBM Cloud "container-registry" CLI plug-in
for the configuration of the container registry, and Docker to build and push the image.
Step 1: Log in to IBM Cloud (IBM Cloud Account TWO
)¶
ibmcloud login (-sso)
Step 2: Log in to IBM Cloud Container Registry¶
ibmcloud cr login
Example output:
Logging in to 'us.icr.io'...
Logged in to 'us.icr.io'.
OK
Step 3: Create a Namespace
inside the IBM Cloud Container Registry¶
Let us name the Namespace
: vend-openshift
.
ibmcloud cr namespace-add vend-openshift
2. Build and push the container image to the IBM Cloud Container Registry (IBM Cloud Account TWO
)¶
Now we build the container image locally and push the image to the IBM Cloud Container Registry
.
Step 1: Build the container image locally¶
We name our container image close to the naming convention of Red Hat.
Format <Registry[:Port]>/<Namespace>/<image>:<tag>
We use the us
region (us).icr.io
of the container registry, with the newly created namespace called vend-openshift
docker build -t "us.icr.io/vend-openshift/vend:v1" -f Dockerfile .
Step 2: Push the container image to the IBM Cloud Container Registry¶
docker push "us.icr.io/vend-openshift/vend:v1"
Step 3: List the existing container images¶
ibmcloud cr image-list
3. Configure the OpenShift project to access the IBM Cloud Container Registry
of IBM Cloud Account ONE
¶
Now we will configure the newly created OpenShift project to access the IBM Cloud Container Registry from IBM Cloud Account ONE
. The following image is a simplified architecture overview:

Step 1: Log in to the OpenShift custer¶
Step 2: Get the existing projects¶
oc get projects
Step 3: Create a new project¶
Name the project vend-ibm
oc new-project vend-ibm
Step 3: Get the existing secrect for the IBM Cloud Container Registry (icr-io
) from the default
project in the OpenShift cluster¶
The secrect is called all-icr-io
. (i[IBM]
c[Container]
.r[Registry]
.io)
oc get secrets -n default | grep icr-io
Example output:
all-icr-io kubernetes.io/dockerconfigjson 1 5d21h
Step 4: Copy the all-icr-io
image pull secret from the default project to our newly created.¶
oc get secret all-icr-io -n default -o yaml | sed 's/default/vend-ibm/g' | oc create -n vend-ibm -f -
In the secret content we do rename the namespace
value from default
to vend-ibm
the yaml below.
apiVersion: v1
data:
.dockerconfigjson: aU5LifX19Q1g
kind: Secret
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: '{"apiVersion":"v1","data":{".dockerconfigjson":"eyJ1TmlJTUo4aVpxnekdzdZKaU5LQ1gifX19"},"kind":"Secret","metadata":{"name":"all-icr-io","namespace":"default"},"type":"kubernetes.io/dockerconfigjson"}'
creationTimestamp: "2021-10-29T16:33:57Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:.dockerconfigjson: {}
f:metadata:
f:annotations:
.: {}
f:kubectl.kubernetes.io/last-applied-configuration: {}
f:type: {}
manager: OpenAPI-Generator
operation: Update
time: "2021-10-29T16:33:57Z"
name: all-icr-io
namespace: default
resourceVersion: "5381"
selfLink: /api/v1/namespaces/default/secrets/all-icr-io
uid: 30defa59-8890-f-a51f-565ee8291c34
type: kubernetes.io/dockerconfigjson
Note: In the future we will use following format
<project_name>-icr-<region>-io
for secret names related to container registries.
Step 5: Verify that the secret is copied/created successfully to the new project.¶
Now we can use the default associated IBM Cloud Container Registry
as an input for our deployments.
oc get secrets -n vend-ibm | grep icr-io
Example output:
all-icr-io kubernetes.io/dockerconfigjson 1 87s
4. Configure the OpenShift project to access the IBM Cloud Container Registry
of IBM Cloud Account TWO
and deploy the container image to OpenShift¶
The following image shows a simplified architecture overview:

Note: For more details please visit the IBM Cloud documentation
Creating an image pull secret with different IAM API key credentials for more control or access to images in other IBM Cloud accounts
.
Step 1: Check if an image pull secret already exists for your default service
account.¶
oc describe serviceaccount default -n vend-ibm
Example output:
In our example we have Image pull secrets: default-dockercfg-76z7g
.
Name: default
Namespace: vend-ibm
Labels: <none>
Annotations: <none>
Image pull secrets: default-dockercfg-76z7g
Mountable secrets: default-token-7zkd7
default-dockercfg-76z7g
Tokens: default-token-7zkd7
default-token-hvgg9
Events: <none>
Step 2: Log on to IBM Cloud Account TWO
¶
ibmcloud login [-sso]
Step 3: Create an IAM new service id¶
I like the naming convention <cluster_name>-<project>-id
, which is provided by the IBM Cloud documentation. In this our the name of the service id
is <roks-gen2-suedbro>-<vend-ibm>-id
.
ibmcloud iam service-id-create <cluster_name>-<project>-id --description "Service ID for IBM Cloud Container Registry in cluster <cluster_name> project <project>"
Example command:
ibmcloud iam service-id-create roks-gen2-suedbro-vend-ibm-id --description "Service ID for IBM Cloud Container Registry in cluster roks-gen2-suedbro project vend-ibm"
Example output:
OK
Service ID roks-gen2-suedbro-vend-ibm-id is created successfully
ID ServiceId-57b78691-24a7-48f1-b263-b1cbad87cbc0
Name roks-gen2-suedbro-vend-ibm-id
Description Service ID for IBM Cloud Container Registry in cluster roks-gen2-suedbro project vend-ibm
CRN crn:v1:bluemix:public:iam-identity::a/641ebfffbac35c8385e1d79b45279e::serviceid:ServiceId-57b78691-24a7-48f1-b263-b1cbad87cbc0
Version 1-be4cfdb528d201078035b25a81ec7f44
Locked false
Step 4: Create a custom IBM Cloud IAM policy
for the newly created cluster service ID that grants access to IBM Cloud Container Registry.¶
ibmcloud iam service-policy-create <cluster_service_ID> --roles <service_access_role> --service-name container-registry [--region <IAM_region>] [--resource-type namespace --resource <registry_namespace>]
ibmcloud iam service-policy-create roks-gen2-suedbro-vend-ibm-id --roles Manager --service-name container-registry --region us-south --resource-type namespace --resource vend-openshift
Example output:
Creating policy under current account for service ID roks-gen2-suedbro-vend-ibm-id as thomas.suedbroecker@...
OK
Service policy is successfully created
Policy ID: 33748d99-ae5c-ed42-9c-5c7e96e836a3
Version: 1-c3692a57cc9c45043965c6f44e2eda
Roles: Manager
Resources:
Service Name container-registry
Region us-south
Resource Type namespace
Resource vend-openshift
Step 5: Create an image pull secret to save the API key credentials in the newly created OpenShift project.¶
We need following parameters and values for the oc command
:
<project>
: Project namevend-ibm
<secret_name>
: We reuse service policy nameroks-gen2-suedbro-vend-ibm-id
.<registry_URL>
: That is our URLus.icr.io
.<api_key_value>
: We need to create an newIAM Key
.<docker_email>
: We should insert an email address.
oc --namespace <project> create secret docker-registry <secret_name> --docker-server=<registry_URL> --docker-username=iamapikey --docker-password=<api_key_value> --docker-email=<docker_email>
- Create an IAM Key
ibmcloud iam api-key-create ibmapikey-roks-gen2-suedbro-vend-ibm-id
Example output:
Creating API key ibmapikey-roks-gen2-suedbro-vend-ibm-id under 641ebfffbac35c8385ee21d79b45279e as thomas.suedbroecker@...
OK
API key ibmapikey-roks-gen2-suedbro-vend-ibm-id was created
Please preserve the API key! It cannot be retrieved after it's created.
ID ApiKey-d79d7054-7e2e-4bea-b718-b58fa956acc7
Name ibmapikey-roks-gen2-suedbro-vend-ibm-id
Description
Created At 2021-11-04T18:33+0000
API Key 17CcgFyamcB7o3SNZysNoMD4RZNUCUimd2360Y
Locked false
- Set region
<region>.icr.io
tous.icr.io
- Execute the command
oc --namespace vend-ibm create secret docker-registry roks-gen2-suedbro-vend-ibm-id --docker-server=us.icr.io --docker-username=iamapikey --docker-password=17CcgFyamcB7ysqNoMD4RZNUCUimd2360Y --docker-email=thomas.suedbroecker@
This is our registry secret name “roks-gen2-suedbro-vend-ibm-id” we will use later.
Example output:
secret/roks-gen2-suedbro-vend-ibm-id created
- Verify created secret in the project
oc get secrets --namespace vend-ibm
Example output:
NAME TYPE DATA AGE
all-icr-io kubernetes.io/dockerconfigjson 1 4h35m
builder-dockercfg-qrksw kubernetes.io/dockercfg 1 5h8m
builder-token-9gjlf kubernetes.io/service-account-token 4 5h8m
builder-token-dlxrr kubernetes.io/service-account-token 4 5h8m
default-dockercfg-76z7g kubernetes.io/dockercfg 1 5h8m
default-token-7zkd7 kubernetes.io/service-account-token 4 5h8m
default-token-hvgg9 kubernetes.io/service-account-token 4 5h8m
deployer-dockercfg-9l5p9 kubernetes.io/dockercfg 1 5h8m
deployer-token-6whjj kubernetes.io/service-account-token 4 5h8m
deployer-token-wnh5k kubernetes.io/service-account-token 4 5h8m
pipeline-dockercfg-6cncv kubernetes.io/dockercfg 1 5h8m
pipeline-token-ptk4t kubernetes.io/service-account-token 4 5h8m
pipeline-token-sr2x7 kubernetes.io/service-account-token 4 5h8m
roks-gen2-suedbro-vend-ibm-id kubernetes.io/dockerconfigjson 1 2m36s
5. Deploy example container image to the OpenShift project¶
The example application needs following configurations:
- Two persistent volume claim to save logs and configurations outside the container
- Two secrets to secure user and admin information
- One configmap to map not secured environment information
- One deployment to define the desired state for the pod
- One service to access the right pod
- One route to access the application from the internet
The following image shows a simplified overview of the dependencies of the container deployment configuration in the project:

Step 1: Create two Persistent Volume Claims¶
oc apply -f pvcs.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: vend-pvc-accesscodes
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: vend-pvc-logs
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
Step 2: Create secretes for the user and admin¶
- User
oc create secret generic vend-user-creds \
--from-literal=VEND_USER=user\
--from-literal=VEND_USER_PASSWORD=user
oc get secret vend-user-creds -o json
- Admin
oc create secret generic vend-admin-creds \
--from-literal=VEND_ADMIN=admin\
--from-literal=VEND_ADMIN_PASSWORD=admin
oc get secret vend-admin-creds -o json
Step 3: Create a configmap¶
oc apply -f configmap.yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: vend-usage
data:
VEND_USAGE: "vend-demo-secret-openshift"
Step 4: Create a deployment¶
oc apply -f deployment.yaml
Here we use the registry secret name “roks-gen2-suedbro-vend-ibm-id“, we defined in step 5.
kind: Deployment
apiVersion: apps/v1
metadata:
name: vend
spec:
selector:
matchLabels:
app: vend
replicas: 1
template:
metadata:
labels:
app: vend
version: v1
spec:
volumes:
- name: vend-volume-accesscodes
persistentVolumeClaim:
claimName: vend-pvc-accesscodes
- name: vend-volume-logs
persistentVolumeClaim:
claimName: vend-pvc-logs
containers:
- name: vend
image: us.icr.io/vend-openshift/vend:v1
livenessProbe:
exec:
command: ["sh", "-c", "curl http://localhost:3000/"]
initialDelaySeconds: 20
readinessProbe:
exec:
command: ["sh", "-c", "curl http://localhost:3000/health"]
initialDelaySeconds: 40
env:
- name: VEND_USAGE
valueFrom:
configMapKeyRef:
name: vend-usage
key: VEND_USAGE
- name: USER
valueFrom:
secretKeyRef:
name: vend-user-creds
key: VEND_USER
- name: USERPASSWORD
valueFrom:
secretKeyRef:
name: vend-user-creds
key: VEND_USER_PASSWORD
- name: ADMINUSER
valueFrom:
secretKeyRef:
name: vend-admin-creds
key: VEND_ADMIN
- name: ADMINUSERPASSWORD
valueFrom:
secretKeyRef:
name: vend-admin-creds
key: VEND_ADMIN_PASSWORD
volumeMounts:
- mountPath: /usr/src/app/accesscodes
name: vend-volume-accesscodes
- mountPath: /usr/src/app/logs
name: vend-volume-logs
ports:
- containerPort: 3000
restartPolicy: Always
imagePullSecrets:
- name: roks-gen2-suedbro-vend-ibm-id
Step 5: Apply the service configuration¶
oc apply -f service.yaml
kind: Service
apiVersion: v1
metadata:
name: vend
labels:
app: vend
spec:
selector:
app: vend
ports:
- port: 3000
name: http
type: NodePort
(optional) Step 6: Describe the service¶
oc describe service vend
Example output:
Name: vend
Namespace: vend-ibm
Labels: app=vend
Annotations: <none>
Selector: app=vend
Type: NodePort
IP Families: <none>
IP: 172.21.121.21
IPs: 172.21.121.21
Port: http 3000/TCP
TargetPort: 3000/TCP
NodePort: http 30661/TCP
Endpoints: 172.17.51.152:3000
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
Step 7: Expose service¶
Here is a useful link to the OpenShift routing topic on an IBM Cloud Red Hat OpenShift cluster Traffic flow in a multizone VPC cluster with a public cloud service endpoint.
oc expose svc vend
Step 8: Get newly created route for our service vend¶
oc get route | grep "vend"
Step 9: Verify the route output in your browser¶
Now open the route and verify the output in your browser:
"{\"message\":\"vend test - vend-demo-secret-openshift\"}"
Step 10: Verify the vend application log file output, that’s saved in the persistent volume claim
1. Get the running pod
oc get pods | grep "vend"
Example output:
vend-6879fc49cc-fv72d 1/1 Running 0 3d3h
2. Access the running pod on it’s command line
oc exec vend-6879fc49cc-fv72d cat ./logs/log.txt
Example output:
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX130402] VEND_USAGE : vend-demo-secret-openshift
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX30403] USER : user
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX30403] USER_PASSWORD : user
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX30403] ADMINUSER : admin
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX0403] ADMINUSER_PASSWORD : admin
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX0407] Info - envDefined==false
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX1906] VEND_USAGE : vend-demo-secret-openshift
¶
Summary¶
It could be useful to be able to use different container image registries for an OpenShift project, the configuration for the IBM Cloud Container Registry works pretty state forward and is good documented. The example application for my cheat sheet contains serval topics to dig into as an example for a simply container implementation using Node.js.
I hope this was useful for you and let’s see what’s next?
Greetings,
Thomas
#ibmcloudcontainerregistry, #ibmcloud, #container, #containerregistry, #openshift, #roks, #container