- By: Thomas Jungbauer ( Lastmod: 2021-10-19 )
Red Hat Quay is an enterprise-quality container registry, which is responsible to build, scan, store and deploy containers. The main features of Quay include:
Security Scanning (with Clair)
and much more.
Quay can be installed as:
Standalone single service
High Availibility service
On OpenShift with an Operator
On OpenShift without an Operator.
For the following Quay Tutorial Quay version 3.3 on OpenShift 4.3/4.4 with an Operator is used. Moreover, a local storage is used, to make the deployment easier and independent to a storage provider. In any case, be sure that for a production environment a "real" storage is used.
Further details can be found at the official Red Hat documentation at: Deploy Red Hat Quay on OpenShift with an Operator
Several components are used to build Quay
Database: used to store metadata (not images)
Redis: stores live builder logs
Quay container registry: Runs Quay as a service
Two types of storages are supported:
Public cloud storage, like Amazon S3, Google Cloud Storage
Private cloud storage, S3 compliant Object Store, Like Ceph RADOS or OpenStack Swift.
|Since I perform the example setup in a limited lab environment, I used local storage. This is not supported for production installations.|
This example installation, covers the configuration of all credentials, but it ignores the configuration of a storage engine. Instead it is using local storage.
Note: Before you begin create a new project called "quay".
From the OpenShift console goto Operators > OperationHub and search for "Red Hat Quay Operator". Be sure NOT to select the community version. Install the Operator using the following settings:
Installation Mode: select the namespace "quay"
Leave the other settings as default.
Once you select "Subscribe", the installation process will take a few minutes. At the end, the operator pods should run inside your namespace and is ready to bse used.
To configure Quay the Custom Resource Definition "QuayEcosystem" must be defined. Below example shows a ready to use example to test the deployment. Several secrets are used in this QuayEcosystem which must be created first. If they are not specified in the QuayEcosystem, then default values would be used. However, it always makes sense to specify passwords :)
Check the article Accessing Red Hat Quay to find the appropriate credentials you need to fetch images from quay.io. Find the section "Red Hat Quay v3 on OpenShift", copy the secret into the file redhat_secret.yaml and create the object in OpenShift:
oc create -f redhat_secret.yaml
The Quay superuser will be able to manage other users or projects. Create the secret by defining username, password and e-mail address:
|The password must have a minimum length of 8 characters.|
oc create secret generic quay-credentials \ --from-literal=superuser-username=<username> \ --from-literal=superuser-password=<password> \ --from-literal=superuser-email=<email>
The Quay configuration is done, by a separate pod, with a separate accessible route. To set the password, create the following secret:
|The password must have a minimum length of 8 characters.|
oc create secret generic quay-config-app \ --from-literal=config-app-password=<password>
As next let’s create the credentials for the database:
oc create secret generic <secret_name> \ --from-literal=database-username=<username> \ --from-literal=database-password=<password> \ --from-literal=database-root-password=<root-password> \ --from-literal=database-name=<database-name>
|It is also possible to use and existing database. To configure this, create the secret as described and add the server parameter, containing the hostname, to the QuayEcosystem definition+|
By default, the operator would install Redis without any password. To specify a password, create the following secret:
oc create secret generic quay-redis-password \ --from-literal=password=<password>
With all the secrets created above, it is time to create the QuayEcosystem. Once it is defined, the operator will automatically start all required services.
The following is an example, using the different secret names (The names should be self explaining) In addition, the following has been defined:
volumeSize = 10GI for the database
keepConfigDeployment to false, this will remove the configuration pod after the deployment.
hostname: to reach the Quay registry under a defined hostname (otherwise a default name would be created)
Clair container scanning is enabled
apiVersion: redhatcop.redhat.io/v1alpha1 kind: QuayEcosystem metadata: name: quayecosystem spec: quay: imagePullSecretName: redhat-quay-pull-secret superuserCredentialsSecretName: quay-credentials configSecretName: quay-config-app deploymentStrategy: Recreate skipSetup: false keepConfigDeployment: false externalAccess: hostname: quay.apps.ocp.ispworld.at database: volumeSize: 10Gi credentialsSecretName: quay-database-credential registryBackends: - name: local local: storagePath: /opt/quayregistry redis: credentialsSecretName: quay-redis-password imagePullSecretName: redhat-quay-pull-secret clair: enabled: true imagePullSecretName: redhat-quay-pull-secret
Once the Quay Operator has deployed all containers, you should see one route (or 2 if you kept Configuration Deployment Container) and can access your Quay installation.
Many customers want to disable the "Create Account" link on the login page (see Figure #3), to prevent that anybody could create a new account. To remove this option, the configuration pod must run.
If the following does not return anything, then the container is not running:
oc get routes -n quay | grep config
If this is the case, modify the resource QuayEcosystem to enable the Configuration UI.
oc edit QuayEcosystem/quayecosystem
and set "KeepConfigDeployment" to true:
quay: [...] keepConfigDeployment: true
After a few minutes another pod, called "quayecosystem-quay-config" will be started and a new route is created:
oc get routes -n quay | grep config quayecosystem-quay-config quayecosystem-quay-config-quay.apps.ocp.ispworld.at quayecosystem-quay-config 8443 passthrough/Redirect None
Login to the Configuration Web Interface with the credentials you specified during the deployment and scroll down to the section "Access Settings".
There remove the checkbox from:
and save and build the configuration.
This will trigger a change on the Quay pod. After it has been recreated (this will take a few minutes), the feature to create a new account is removed from the Login page.
The following quick steps through Quay are the steps of the Quay tutorial, which can be seen at the Quay WebUI at the "Tutorial" tab.
To login via docker CLI simply use:
docker login <your selected hostname for quay>
|Docker expects a valid certificate. Such certificate could be added to the definition of QuayEcosystem. However, I did not create a certificate for this lab. To allow untrusted certificates, on a Mac, simply download the certificates (For Chrome: you can drag and drop the certificate from the browser to your Desktop, for Firefox, you need to open the Options menu and export the certificates.). After that double click both certificates (the root and the site certificate), which will install them on you local Keychain. Open the Keychain on you Mac, find the appropriate certificates and set both to "Always trust"|
The next step to create a new image is to create a container. For this example the busybox base image is used.
docker run busybox echo "fun" > newfile
This will pull the latest image of busybox and create a container:
Unable to find image 'busybox:latest' locally latest: Pulling from library/busybox d9cbbca60e5f: Pulling fs layer d9cbbca60e5f: Verifying Checksum d9cbbca60e5f: Download complete d9cbbca60e5f: Pull complete Digest: sha256:836945da1f3afe2cfff376d379852bbb82e0237cb2925d53a13f53d6e8a8c48c Status: Downloaded newer image for busybox:latest
With "docker ps" the running container is shown. Remember the Container ID for further steps. In this case fc3e9bb1e9da.
docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fc3e9bb1e9da busybox "echo fun" 3 minutes ago Exited (0) 3 minutes ago relaxed_proskuriakova
Once a container has terminated in Docker, the next step is to commit the container to an image. To do so we will use "docker commit" command. As name for the repository I took superapp.
docker commit fc3e9bb1e9da quay.apps.ocp.ispworld.at/quay/superapp
The final step is to push the image to our repository, where it will be stored for future use.
docker push quay.apps.ocp.ispworld.at/quay/superapp
Clair is used to scan containers about possible security risks. It imports vulnerability data permanently from a known source and creates a list of threats for an image.
To test such scanning, we pull the "Universal Base Image RHEL 7" from Red Hat. I am using version 7.6 since this is already quite old and we expect some known vulnerabilities for this image.
First you need to login to Red Hat Registry:
docker login registry.redhat.io Username: <Username> Password: <Password> Login Succeeded
Then let’s pull the UBI Image 7.6 (instead of the latest)
docker pull registry.redhat.io/ubi7/ubi:7.6
Before we can push it to our Quay registry, we need to tag it:
docker tag registry.redhat.io/ubi7/ubi:7.6 quay.apps.ocp.ispworld.at/quay/ubi7:7.6
If we now check the local images, we see that there are two UBI images.
docker images REPOSITORY TAG IMAGE ID CREATED SIZE quay.apps.ocp.ispworld.at/quay/ubi7 7.6 247ee58855fd 10 months ago 204MB registry.redhat.io/ubi7/ubi 7.6 247ee58855fd 10 months ago 204MB
Now it is possible to push the image to the Quay repository.
docker push quay.apps.ocp.ispworld.at/quay/ubi7:7.6
Finally the image is available inside our Registry and Clair will queue it for a security scan.
Once the scan is finished, possible found issues are shown under the "Repository Tags".
When you click on then, you will see a detailed result page, with all vulnerabilities found: