Documentation Nexus Repository Manager 3.0

Chapter 8. Private Registry for Docker

Available in Nexus Repository OSS and Nexus Repository Pro

8.1. Introduction

Docker containers and their usage have revolutionized the way applications and the underlying operating system are packaged and deployed to development, testing and production systems.

The creation of the Open Container Initiative, and the involvement of a large number of stakeholders, guarantees that the ecosystem of tools around the lightweight containers and their usage will continue to flourish.

Docker Hub is the original registry for Docker container images and it is being joined by more and more other publicly available registries such as the Google Container Registry and others.

Nexus Repository Manager Pro and Nexus Repository Manager OSS support Docker registries as the Docker repository format for hosted and proxy repositories. You can expose these repositories to the client-side tools directly or as a repository group, which is a repository that merges and exposes the contents of multiple repositories in one convenient URL.

This allows you to reduce time and bandwidth usage for accessing Docker images in a registry as well as share your images within your organization in a hosted repository. Users can then launch containers based on those images, resulting in a completely private Docker registry with all the features available in the repository manager.

[Tip]

Docker is a fast moving project and requires usage of current operating system versions and tools. For example, usage of Red Hat Enterprise Linux 6 is simply not supported. Please use the official documentation as reference and help for your usage.

8.2. SSL and Repository Connector Configuration

Docker relies on secure connections using SSL to connect to the repositories. You are therefore required to expose the repository manager to your client tools via HTTPS. This can be configured via an external proxy server or directly with the repository manager. Further details can be found in Section 5.9.4, “Inbound SSL - Configuring to Serve Content via HTTPS”.

Interaction of the docker client with repositories requires specific ports to be used. These can be configured in the repository configuration in the Repository Connectors section. In order for this to work on your network, you need to ensure that the chosen ports are available in your organization and not used by some other application, and that no firewall or other network configuration prevents connectivity.

[Note]

The docker client does not allow a context as part of the path to a registry, as the namespace and image name are embedded in the URLs it uses. This is why requests to repositories on the repository manager are served on a specific and separate port from the rest of the application instead of how most other repositories serve content via a path i.e. <nexus-hostname>/<repositoryName>/<path to content>.

The recommended minimal configuration requires one port for a Docker repository group used for read access to all repositories and one port for each hosted Docker repository that will receive push events from your users. The Repository Connectors configuration displayed in Figure 8.1, “Repository Connector Configuration” is available in the configuration for proxy and hosted Docker repositories as well as Docker repository groups.

figs/web/repository-connectors.png

Figure 8.1. Repository Connector Configuration


If you have configured the repository manager to use HTTPS directly, you have to configure a HTTPS repository connector. If an external proxy server translates incoming HTTPS requests to HTTP and forwards the request to the repository manager via HTTP you have to configure the respective HTTP port.

[Tip]

A configured context-path for the user interface does not affect the repository connector URLs used by Docker. E.g. if your repository manager instance is configured to be available at http://localhost:8081/nexus instead of the default root context http://localhost:8081/, the URLs for your Docker repositories will still only use the configured port for the repository and omit the context path in the URL. This is a side-effect of the the fact that Docker does not support context paths in the registry API.

8.2.1. Tips for SSL Certificate Usage

Nexus Repository Manager is not configured with HTTPS connectors by default as it requires an SSL certificate to be generated and configured manually.

The requirement of Docker to use HTTPS forces the usage of SSL certificates. By default, Docker looks up the validity of the certificate by checking with certificate authorities. If you purchased a certificate that is registered with these authorities, all functionality works as desired.

If you create a certificate yourself with tools such as openssl, it is self-signed and not registered. Using a self-signed certificate requires further configuration steps to ensure that Docker can explicitly trust it.

[Warning]

Docker Daemon can stand up instances with the --insecure-registry flag to skip validation of a self-signed certificate. But the repository manager does not support the use of the flag, as it generates known bugs and other implementation issues.

To generate a trustworthy self-signed certificate for the repository manager use keytool, a utility that lets you manage your own private key pairs and certificates. See our knowledge base article to learn how to configure the utlilty.

8.3. Support for Docker Registry API

The Docker client tools interact with a repository via the registry API. It is available in version 1 (V1) and version 2 (V2). The newer V2 will completely replace the old V1 in the future. Currently Docker Hub and other registries as well as other tools use V2, but in many cases fall back to V1. E.g., search is currently only implemented in V1.

Nexus Repository Manager supports V1 as well as V2 of the API. All Docker repository configurations contain a section to configure Docker Registry API Support. If you activate Enable Docker V1 API for a repository it is enabled to use V1 as a fallback from V2. Without this option any V1 requests result in errors from the client tool.

[Tip]

Generally V1 support is only needed for repository groups that will be used for command line-based searches, when any client side tools in use require V1 or when a upstream proxy repository requires V1. If you are unsure if your setup uses these or V1, it is recommended to activate V1 support as there should be no harm if it is not needed.

8.4. Proxy Repository for Docker

Docker Hub is the common registry used by all image creators and consumers. To reduce duplicate downloads and improve download speeds for your developers and CI servers, you should proxy Docker Hub and any other registry you use for Docker images.

To proxy a Docker registry, you simply create a new docker (proxy) as documented in Section 4.3, “Repository Management” in details.

Minimal configuration steps are:

  • Define Name
  • Define URL for Remote storage
  • Enable Docker V1 API support, if required by the remote repository
  • Select correct Docker index, further configure Location of Docker index if needed
  • Select Blob store for Storage

Optionally you can configure Repository Connectors as explained in Section 8.2, “SSL and Repository Connector Configuration”, although typically read access is done via a repository group and not a proxy repository directly, and write access is done against a hosted repository.

The Remote Storage has to be set to the URL of the remote registry you want to proxy. The configuration for proxying Docker Hub uses the URL https://registry-1.docker.io for the Remote storage URL.

The Proxy configuration for a Docker proxy repository includes a configuration URL to access the Docker Index. The index is used for requests related to searches, users, docker tokens and other aspects. The registry and the index are typically co-hosted by the same provider, but can use different URLs. E.g. the index for Docker Hub is exposed at https://index.docker.io/.

The default option Use proxy registry (specified above) will attempt to retrieve any index data from the same URL configured as the Remote storage URL.

The option to Use Docker Hub fulfills any index related requests by querying the Docker Hub index at https://index.docker.io/. This configuration is desired when the proxy repository is Docker Hub itself or any of its mirrors.

The option to use a Custom index allows you to specify the URL of the index for the remote repository.

It is important to configure a correct pair of Remote Storage URL and Docker Index URL. In case of a mismatch, search results potentially do not reflect the content of the remote repository and other problems can occur.

[Tip]

Just to recap, in order to configure a proxy for Docker Hub you configure the Remote Storage URL to https://registry-1.docker.io, enable Docker V1 API support and for the choice of Docker Index select the Use Docker Hub option.

8.5. Hosted Repository for Docker (Private Registry for Docker)

A hosted repository using the Docker repository format is typically called a private Docker registry. It can be used to upload your own container images as well as third-party images. It is common practice to create two separate hosted repositories for these purposes.

To create a Docker hosted repository, simply create a new docker (hosted) repository as documented in Section 4.3, “Repository Management”.

Minimal configuration steps are:

  • Define Name
  • Select Blob store for Storage

If you add a Repository Connectors configuration as documented in Section 8.2, “SSL and Repository Connector Configuration” you can push images to this repository, and subsequently access them directly from the hosted repository or ideally from the Docker repository group as documented in Section 8.6, “Repository Groups for Docker”.

By default this setup will allow repeated deployment of images. If you want to enforce new deployments using different versions, set the Deployment Policy to Disable Redeploy.

8.6. Repository Groups for Docker

A repository group is the recommended way to expose all your repositories for read access to your users. It allows you to pull images from all repositories in the group without needing any further client side configuration after the initial setup. A repository group allows you to expose the aggregated content of multiple proxy and hosted repositories with one URL to your tools.

To create a Docker repository group, simply create a new docker (group) repository as documented in Section 4.3, “Repository Management”.

Minimal configuration steps are:

  • Define Name
  • Select Blob store for Storage
  • Add Docker repositories to the Members list in the desired order

Typically the member list includes a mixture of proxy and hosted repositories to allow access to public as well as private images.

Using the Repository Connectors port of the repository group and the URL of the repository manager in your client tool gives you access to the container images in all repositories from the group. Any new images added as well as any new repositories added to the group will automatically be available.

[Tip]

Check out this repository configuration demonstrated in a video.

8.7. Authentication

If access to a repository requires the user to be authenticated, docker will check for authentication access in the ~/.docker/config.json file. If authentication is not found, some actions will prompt for authentication but otherwise a docker login command will be required before the actions can be performed. Typically this is required when anonymous access to the repository manager is disabled or the operation requires authentication.

The docker login command observes the following syntax for the desired repository or repository group:

docker login <nexus-hostname>:<repository-port>

Provide your repository manager credentials of username and password as well as an email address. This authentication is persisted in ~/.docker/config.json and reused for any subsequent interactions against that repository. Individual login operations must be performed for each repository and repository group you want to access in an authenticated manner.

[Tip]

Specifically when planning to push to a repository a preemptive login operation is advisable as it removes the need for use interaction and is therefore suitable for continuous integration server setups and automated scenarios.

8.8. Accessing Repositories

You can browse Docker repositories in the user interface and inspect the components and assets and their details as documented in Section 3.4, “Browsing Repositories and Repository Groups”.

When using the docker command line client, or any other tools using the repository manager indirectly, the common structure for commands can be:

docker <command> <nexus-hostname>:<repository-port>/<namespace>/<image>:<tag>
docker search <nexus-hostname>:<repository-port>/<search-term>

with

command
a docker command such as push or pull
nexus-hostname
the IP number or hostname of your repository manager
repository-port
the port configured as the repository connector for the specific repository or repository group
namespace
the optional namespace of the specific image reflecting the owner, if left out this will silently default to /library and utilize Docker Hub
image
the name of the Docker image
tag
the optional tag of the image, defaulting to latest when omitted
search-term
the search term or name of the image to search for

The most important aspects are to know and use the correct hostname for the repository manager and the port for the desired repository or repository group.

8.9. Searching

Searching for Docker images can be performed in the user interface as described in Section 3.3, “Searching for Components”. This search will find all Docker images that are currently stored in repositories, either because they have been pushed to a hosted repository or they have been proxied from an upstream repository and cached in the repository manager.

The more common use case for a Docker user is to search for images on the command line:

$ docker search postgres
NAME      DESCRIPTION                                  STARS  OFFICIAL  AUTOMATED
postgres  The PostgreSQL object-relational database... 1025   [OK]
...

By default this search uses Docker Hub as preconfigured in docker and will only find images available there. A more powerful search is provided by the repository manager when searching against a repository group. An example looking for a postgres image on Nexus Repository Manager OSS running on the host nexus.example.com and exposing a repository group with a repository connector port of 18443 looks like this:

docker search nexus.example.com:18443/postgres

The results include all images found in the repositories that are part of the repository group. This includes any private images you have pushed to your hosted repositories. In addition it includes all results returned from the remote repositories configured as proxy repositories in the group. Searching in a specific repository can be achieved by using the repository connector port for the specific repository.

8.10. Pulling Images

Downloading images, also known as pulling, from the repository manager can be performed with the docker pull command. The only necessary additions are the hostname or IP address of the repository manager as well as the repoisitory connector port for the repository or repository group to download from:

docker pull <nexus-hostname>:<repository-port>/<image>

The preferred setup is to proxy all relevant sources of public/private images you want to use, with Docker Hub being the most common choice. Then configure one or more hosted repositories to contain your own images, and expose these repositories through one repository group.

Examples for various images from Nexus Repository Manager running on the host nexus.example.com and exposing a repository group with a repository connector port of 18443 are:

docker pull nexus.example.com:18443/ubuntu
docker pull nexus.example.com:18443/bitnami/node
docker pull nexus.example.com:18443/postgres:9.4

These snippets download the official ubuntu image, the node image from the user bitnami and the version 9.4 of the postgres image. Official images such as ubuntu or postgres belong to the library user on Docker Hub and will therefore show up as library/ubuntu and library/postgres in the repository manager.

After a successful pull you can start the container with run.

8.11. Pushing Images

Sharing an image can be achieved, by publishing it to a hosted repository. This is completely private and requires you to tag and push the image. When tagging an image, you can use the image identifier (imageId). It is listed when showing the list of all images with docker images. Syntax and an example (using imageId) for creating a tag are:

docker tag <imageId or imageName> <nexus-hostname>:<repository-port>/<image>:<tag>
docker tag af340544ed62 nexus.example.com:18444/hello-world:mytag

Once the tag, which can be equivalent to a version, is created successfully, you can confirm its creation with docker images and issue the push with the syntax:

docker push <nexus-hostname>:<repository-port>/<image>:<tag>
[Important]

Note that the port needs to be the repository connector port configured for the hosted repository to which you want to push to. You can not push to a repository group or a proxy repository.

A sample output could look like this:

$ docker push nexus.example.com:18444/hello-world:labeltest
The push refers to a repository [nexus.example.com:18444/hello-world] (len: 1)
Sending image list
Pushing repository nexus.example.com:18444/hello-world (1 tags)
535020c3e8ad: Image successfully pushed
af340544ed62: Image successfully pushed
Pushing tag for rev [af340544ed62] on
{https://nexus.example.com:18444/repository/docker-internal/v1/repositories/hello-world/tags/labeltest}

Now, this updated image is available in the repository manager and can be pulled by anyone with access to the repository, or the repository group, containing the image. Pulling the image from the repository group exposed at port 18443 can be done with:

docker pull nexus.example.com:18443/hello-world:labeltest

Prior to push, and depending on your configuration, repository manager login credentials may be required before a push or pull can occur.

[Tip]

Searching, Browsing, Pushing and Pulling are all showcased in this video.

Pushing large images can result in failures due to network interruptions and other issues. These partial uploads result in temporary storage for these transfers in the repository manager filling up. The task Purge incomplete docker uploads can be configured to delete these files. Further documentation can be found in Section 4.2.6, “Configuring and Executing Tasks”.