An image registry stores and versions container images for distribution to container runtime engines such as Docker, Podman, and others. Images are typically pulled and pushed using the respective commands of the runtime engine. Another benefit is that registries can centralize the distribution of images in an environment. Most runtimes come with default registries to pull and push from, but you might want to have your own personal/private registry where you can control what images are available for your runtimes.
This article outlines the steps needed to implement a private registry as a container and store images in /opt/registry for internal use. Podman is the container engine and htpasswd provides authentication.
Install Podman and httpd-tools
Install the podman package to run the registry. The httpd-tools package provides the htpasswd utility for authentication.
# yum install -y podman httpd-tools
Create folders for the registry
The registry will be stored in /opt/registry/ on the host system and the respective directories are mounted in the container running the registry.
# mkdir -p /opt/registry/{auth,certs,data}
- The Auth subdirectory stores the
htpasswdfile used for authentication. - The Certs subdirectory stores certificates used by the registry for
- authentication.
- The Data directory stores the actual images stored in the registry.
Note - Creating the directories on removable storage makes the registry portable for disconnected/restricted networks.
Generate credentials for accessing the registry
Authentication is provided by a simple htpasswd file and also an SSL key pair.
htpasswd username and password
Use the htpasswd utility to generate a file containing the credentials for accessing the registry:
# htpasswd -bBc /opt/registry/auth/htpasswd registryuser registryuserpassword
- b provides the password via command.
- B stores the password using Bcrypt encryption.
- c creates the file.
- Username is registryuser.
- Password is registryuserpassword.
A Bcrypt Htpasswd file named htpasswd will be created in the /opt/registry/auth/ directory.
TLS key pair
The registry is secured with TLS by using a key and certificate signed by a trusted authority (internal or external) or by a simple self-signed certificate. To use a self-signed certificate:
# openssl req -newkey rsa:4096 -nodes -sha256 -keyout /opt/registry/certs/domain.key -x509 -days 365 -out /opt/registry/certs/domain.crt
- req tells OpenSSL to generate and process certificate requests.
- -newkey tells OpenSSL to create a new private key and matching certificate request.
- rsa:4096 tells OpenSSL to generate an RSA key with 4096 bits.
- -nodes tells OpenSSL there is no password requirement for the private key. The private key will not be encrypted.
- -sha256 tells OpenSSL to use the sha256 to sign the request.
- -keyout tells OpenSSL the name and location to store new key.
- -x509 tells OpenSSL to generate a self-signed certificate.
- -days tells OpenSSL the number of days the key pair is valid for.
- -out tells OpenSSL where to store the certificate.
Enter the respective options for your certificate. The CN= value is the hostname of your host. The host's hostname should be resolvable by DNS or the /etc/hosts file.
Note: If the registry is not secured using TLS, the insecure setting in the /etc/containers/registries.conf file may have to be configured for the registry.
The certificate will also have to be trusted by your hosts and clients:
# cp /opt/registry/certs/domain.crt /etc/pki/ca-trust/source/anchors/
# update-ca-trust
# trust list | grep -i "<hostname>"
Start the registry
The next step involves running the registry image with an exposed port (5000) and mounted volumes of the respective directories created earlier.
The command to start the registry:
# podman run --name myregistry \
-p 5000:5000 \
-v /opt/registry/data:/var/lib/registry:z \
-v /opt/registry/auth:/auth:z \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-v /opt/registry/certs:/certs:z \
-e "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt" \
-e "REGISTRY_HTTP_TLS_KEY=/certs/domain.key" \
-e REGISTRY_COMPATIBILITY_SCHEMA1_ENABLED=true \
-d \
docker.io/library/registry:latest
The details of the options are:
- --name myregistry names the container myregistry.
- -p 5000:5000 exposes port 5000 in the container as port 5000 on the host.
- -v /opt/registry/data:/var/lib/registry:z mounts
/opt/registry/dataon the host as/var/lib/registryin the container with the correct SELinux context. - -v /opt/registry/auth:/auth:z mounts
/opt/registry/authon the host as/authin the container with the correct SELinux context. - -v opt/registry/certs:/certs:z mounts
/opt/registry/certson the hosts as/certsin the container with the correct SELinux context. - -e "REGISTRY_AUTH=htpasswd" uses an
bcryptencryptedhtpasswdfile for authentication. File location set by container's REGISTRY_AUTH_HTPASSWD_PATH environment variable. - -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" specifies the realm to use for
htpasswd. - -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd uses the bcrypt-encrypted
/auth/htpasswdfile in the container. - -e "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt" sets path to certificate file.
- -e "REGISTRY_HTTP_TLS_KEY=/certs/domain.key" sets path to private key.
- -e REGISTRY_COMPATIBILITY_SCHEMA1_ENABLED=true provides backward compatibility for schema1 manifests.
- -d docker.io/library/registry:latest is a registry application that allows for the storage and distribution of images.
Note: If a firewall is running on the hosts, the exposed port (5000) will need to be permitted.
# firewall-cmd --add-port=5000/tcp --zone=internal --permanent
# firewall-cmd --add-port=5000/tcp --zone=public --permanent
# firewall-cmd --reload
Verify access to registry
The curl command can be used to access the registry:
# curl https://hostname:5000/v2/_catalog
{"repositories":[]}
The certificate can be verified using:
# openssl s_client -connect <servername>:5000 -servername <servername>
Be sure to trust the certificate from earlier or use curl's -k switch to ignore certificate verification.
Work with the registry
The registry can be accessed and interacted with just like any other registry such as registry.access.redhat.com, registry.redhat.io, docker.io, and/or quay.io.
Log in to the registry
Use the podman login command to log into the registry:
# podman login <hostname>:5000
Enter Username:xxxxxxxx
Enter Password:yyyyyyyy
Login Succeeded!
Your credentials will be Base64 encoded into /run/user/0/containers/auth.json by default.
When working with OpenShift and using an alternate/mirror registry for disconnected/air-gapped environments, the contents of this file can be added to your pull secret file. You can also add your pull secret file as a command-line option to podman login and your credentials will be added to the file upon login.
# podman login <hostname>:5000 --authfile <pull secret file>
Enter Username:xxxxxxxx
Enter Password:yyyyyyyy
Login Succeeded!
Log out of the registry
Use podman logout to log out of the registry:
# podman logout <hostname>:5000
Removed login credentials for registry.tkagn.io:5000
Credentials will be removed from /run/user/0/containers/auth.json or from any file you specify via the --authfile parameter.
Push/pull images to the registry
To pull images from the registry, prepend the registry location to the repository/image name.
Example: podman pull <Registry Hostname>:<Registry Port>/<Repository>/<Image Name>
To push to the registry, use podman tag to first tag the image and the registry location, and then push the image.
Example: podman tag <image id|<repo name/image name>> registry:5000/<repo>/<image>
# podman pull registry.access.redhat.com/ubi8/ubi:latest
Trying to pull registry.access.redhat.com/ubi8/ubi...
Getting image source signatures
…
Storing signatures
# podman login <registry hostname>:<port>
Enter Username:xxxxxx
Enter Password:yyyyyyy
Login Suceeded!
# podman tag registry.access.redhat.com/ubi8/ubi:latest <registry
hostname>:<port>/ubi8/ubi:latest
# podman push <registry hostname>:<port>/ubi8/ubi:latest
Getting image source signatures
Copying blob 226bfaae015f done
…
Storing signatures
You can verify the images has been uploaded to the registry via the curl command:
# curl -u <username>:password https://<registry host>:<port>/v2/_catalog
{"repositories":["ubi8/ubi"]}
With the private registry implemented, you can edit /etc/containers/registries.conf to include the private registry in the list of supported registries.
Lifecycle
Start registry:
# podman run --name myregistry -p 5000:5000 -v
/opt/registry/data:/var/lib/registry:z -v /opt/registry/auth:/auth:z -e
"REGISTRY_AUTH=htpasswd"
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e
REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd -v /opt/registry/certs:/certs:z -e
REGISTRY_COMPATIBILITY_SCHEMA1_ENABLED=true -d docker.io/library/registry:latest
Stop registry:
# podman stop myregistry
Remove registry:
# podman rm myregistry
Delete registry image:
# podman rmi registry:latest
Remove certificate:
# rm /etc/pki/ca-trust/source/anchors/domain.crt
# update-ca-trust
# trust list | grep "<hostname>"
Alternatives
Another option is to use Quay as a private registry, which offers many more features.
Conclusion
With this personal/private registry in place, you can provide a central point of distribution for your in-house images that can be stored and maintained. A private registry can also come in handy in disconnected and air-gapped environments. I hope you find this information useful for your situation.
[ Getting started with containers? Check out this free course. Deploying containerized applications: A technical overview. ]
Sobre el autor
Stephen Wilson is a Senior Storage Consultant with Red Hat, Inc. He has over 20 years of experience in information systems management. His professional interests include system administration, cybersecurity, cloud technologies, and virtualization.
Stephen lives in Meridian, MS with his wife Tan and two boys, Stephen and Matthew. Stephen's personal hobbies include weightlifting, running (yes for fun), and basketball. Stephen is active in his community and volunteers his time to try and make things better for everybody
Más como éste
Red Hat and Sylva unify the future for telco cloud
Bridging the gap: Secure virtual and container workloads with Red Hat OpenShift and Palo Alto Networks
The Containers_Derby | Command Line Heroes
Can Kubernetes Help People Find Love? | Compiler
Navegar por canal
Automatización
Las últimas novedades en la automatización de la TI para los equipos, la tecnología y los entornos
Inteligencia artificial
Descubra las actualizaciones en las plataformas que permiten a los clientes ejecutar cargas de trabajo de inteligecia artificial en cualquier lugar
Nube híbrida abierta
Vea como construimos un futuro flexible con la nube híbrida
Seguridad
Vea las últimas novedades sobre cómo reducimos los riesgos en entornos y tecnologías
Edge computing
Conozca las actualizaciones en las plataformas que simplifican las operaciones en el edge
Infraestructura
Vea las últimas novedades sobre la plataforma Linux empresarial líder en el mundo
Aplicaciones
Conozca nuestras soluciones para abordar los desafíos más complejos de las aplicaciones
Virtualización
El futuro de la virtualización empresarial para tus cargas de trabajo locales o en la nube