This is a solution of a common problem with Nexus Docker repositories. The administrator has to expose port for "pull", another port for "push", other ports for each hosted repository. This solution is about leveraging Nginx reverse proxy to avoid using these ports.
Given :
- Nexus hostname is "nexus.example.com"
- Nexus web port is 8081
- A hosted repository is named "docker-hosted"
- A group repository is named "docker-group"
- Your nginx (with the nginx.conf of this gist) will run for example under cregistry.example.com
The following Nginx configuration file is for a reverse proxy without the need to expose connector ports from nexus :
docker pull cregistry.example.com/myimage
lets Nginx forward the request to "docker-group"docker push cregistry.example.com/myimage
lets Nginx forward the request to "docker-hosted"
-
If you have more than one hosted repository, create another Nginx reverse proxy for it, then aggregate them using a parent Nginx reverse proxy that forwards the request according to certain criteria (.i.e: Host header).
-
All Nexus repositories must have consistent configuration of authentication: Either all require authentication, or all don't.
-
If TLS is enabled with Nexus, change
proxy_set_header X-Forwarded-Proto "http";
byproxy_set_header X-Forwarded-Proto "https";
Thanks for the config! I wrote the config similarly, but through proxy_pass instead of rewrite (could share if will be needed), and there's a nuance:
Let's say my Nexus has a domain name mycompany.com. There are three standard Docker repositories: docker-hosted, docker-proxy, docker-group. The docker-group includes both docker-hosted and docker-proxy. Nexus 3.77.
Let's say there's this dockerfile:
FROM memcached:1.6.38
RUN do something
...
The server itself is configured to use mycompany.com as a mirror-registry, so in the FROM line we don't need to explicitly write mycompany.com/memcached:1.6.38, the image will be pulled through docker-proxy and saved.
Then I execute "docker build -t mycompany.com/memcached:v1.0"
After building "docker push mycompany.com/memcached:v1.0"
And the push crashes, the layers which has base FROM image (mmecached:1.6.38) never gets pushed to the docker-hosted repo.
Here's the problem: Docker tries to mount the layer (Docker's internal optimization mechanism) of the base image from FROM, which is located in the docker-proxy repository, to the docker-hosted repository. It can't do this (because these are different repositories but the image name is the same), it keeps trying again until timeout. I managed to fix it by removing the base image from the docker-proxy repo and pushing again.
It's clear that the most obvious solution is: simply don't name the resulting image based on the base image name, i.e., if the base is memcached:1.6.38, name yours, for example, mycompany-memcached:1.6.38 and push it.
I want to understand if everyone really adheres to this approach, or if I'm just missing something in my configuration.
TLDR Why I can't build and push to docker-hosted repo an image with the same name, as one of the images in the docker-proxy (i.e. I used FROM node:14 , docker-proxy now has node:14 saved, built an image and named it node:14, and tried to push it, it will fail for me, because docker tried to get node:14 layers from proxy-repo into the hosted-repo, is this a normal behaviour?).