Search code examples
dockernginxdocker-composedocker-registrynexus3

Serve docker repository on non-root path (nginx + Sonatype Nexus)


We have several Docker repositories, served with a Sonatype Nexus server.

The problem is that we want to serve them from paths instead of serving them on different domains. The reason is simple: it is easier to configure new paths than new domains, with each subdomain registration and SSL certificate. In addition, there are some security issues too.

Can it be done?


Solution

  • After a while, I've discovered that there are two steps: the login and the normal usage.

    Since the installation has a nginx and the nexus servers in a docker-compose, I can refer the nexus host as "nexus", and access just by http. The SSL certificate is resolved in the nginx using the usual nginx configuration

    In order to make the login to work, it is important to redirect the path /v2/ to a docker repository. This can be done with nginx:

    location /v2/ {
       proxy_set_header    Host $host;
       proxy_set_header    X-Real-IP $remote_addr;
       proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header    X-Forwarded-Proto $scheme;
       proxy_pass          http://nexus:10000;
       proxy_read_timeout  90;
    }
    

    Notice it assumes the nexus configuration for the docker repository is listening internally at 10000 port (http). With this configuration, the docker login should already work, but you cannot pull any image.

    In order to access the images, it is important to rewrite the URIs (please, place this configuration over the /v2/ configuration shown before):

    location ~ /v2/repository/docker-repo1/(.*) {
      proxy_set_header    Host $host;
      proxy_set_header    X-Real-IP $remote_addr;
      proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header    X-Forwarded-Proto $scheme;
      proxy_pass          http://nexus:10000/v2/$1;
      proxy_read_timeout  90;
    }
    

    And it is easy to realize that you can create a second repository, listening in port 10001, with configuration:

    location ~ /v2/repository/docker-repo2/(.*) {
      proxy_set_header    Host $host;
      proxy_set_header    X-Real-IP $remote_addr;
      proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header    X-Forwarded-Proto $scheme;
      proxy_pass          http://nexus:10001/v2/$1;
      proxy_read_timeout  90;
    }
    

    And it is done.

    Remember it is important to maintain the /v2/ configuration (the one for the login) after all others or will never be reached.

    I'm not sure if all the requirements about authorization will work as expected... I will update this answer if I see any problem.