Running a private Docker registry with Nexus 3
For quite a while I am looking for a private Docker registry server which is easy to set up and fairly trivial to run in our IT infrastructure, e.g. being able to connect to our central LDAP server for user management. A few months back I realized that the next major version of Nexus will be able to host docker images. Since we already have a nexus instance running this seemed like a natural fit for us. Finally, I found some time to play with the current M7 release which already offers the docker registry feature.
Running Nexus is simple, all it requires is Java 1.8. To make things a bit more complicated tried to run Nexus in a docker container with haproxy in front. To be able to run Nexus 3 as a docker registry I needed to tweak haproxy because the docker registry in Nexus 3 is running on a different port. I needed to distinguish between regular requests for Nexus and the requests of the docker client hitting the docker registry. Luckily the docker client exposes itself in the user agent sent to the server. Thus, I configured the haproxy frontend this way:
frontend haproxy-http
bind 192.168.65.1:80
acl host_is_nexus hdr(host) -i nexus.mydomain.loc
acl client_is_docker hdr_sub(user-agent) -i docker
mode http
reqadd X-Forwarded-Proto:\ http
use_backend docker-backend if host_is_nexus client_is_docker
use_backend nexus-backend if host_is_nexus !client_is_docker
frontend haproxy-https
bind 192.168.65.1:443 ssl crt /etc/ssl/private/mydomain.loc.pem
acl host_is_nexus hdr(host) -i nexus.mydomain.loc
acl client_is_docker hdr_sub(user-agent) -i docker
mode http
reqadd X-Forwarded-Proto:\ https
use_backend docker-backend if host_is_nexus client_is_docker
use_backend nexus-backend if host_is_nexus !client_is_docker
The regular nexus backend configuration looks like this:
backend nexus-backend
balance leastconn
cookie JSESSIONID prefix
mode http
option httpclose
option forwardfor
redirect scheme https if !{ ssl_fc }
server node1 127.0.0.1:8081
The backend configuration for the docker registry looks quite similar but hits a different port. The port needs to be configured in Nexus 3 during the hosted docker setup. Since SSL termination is done via haproxy the docker registry of Nexus 3 is configured for http access only. My first try to configure an https connection for the docker registry resulted in a org.sonatype.nexus.bootstrap.jetty.UnsupportedHttpSchemeException exception.
backend docker-backend
balance leastconn
cookie JSESSIONID prefix
mode http
option httpclose
option forwardfor
redirect scheme https if !{ ssl_fc }
server node1 127.0.0.1:8082
To connect to the private docker registry use the following command:
docker login nexus.mydomain.loc
In case the command above gives you a "client is newer than server" error, try to force the docker client to run with a different api version. In my case the server was running version 1.21:
DOCKER_API_VERSION=1.21 docker login nexus.mydomain.loc
Next up: Waiting for the final Nexus 3 release ;)