Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logging in to private docker registry v2 behind haproxy

I am trying to set up a new Docker Registry (v2) with HAProxy. For the Docker Registry I am using the image from the docker hub and running it with docker run -d -p 5000:5000 -v /path/to/registry:/tmp/registry registry:2.0.1. And this is a subset of my HAProxy configuration:

global
    chroot /var/lib/haproxy
    user haproxy
    group haproxy
    daemon
    tune.ssl.default-dh-param 2048

userlist auth_list
    group docker_registry users root
    user root password ***PASSWORD***

backend docker-registry
    server 127.0.0.1:5000_localhost 127.0.0.1:5000 cookie 127.0.0.1:5000_localhost 

frontend shared-frontend
    mode http
    bind *:80
    bind *:443 ssl crt *** CERT FILES ***
    option accept-invalid-http-request

    acl domain_d.mydomain.com hdr(host) -i d.mydomain.com
    acl auth_docker_registry_root http_auth(auth_list) root
    redirect scheme https if !{ ssl_fc } domain_d.mydomain.com
    http-request auth realm Registry if !auth_docker_registry_root { ssl_fc } domain_d.mydomain.com
    use_backend docker-registry if domain_d.mydomain.com

The important things to note are that I am using HAProxy to do SSL termination and HTTP auth rather than the registry.

My issue occurs when I try to login to the new registry. If I run docker login https://d.mydomain.com/v2/ then enter the user root and password I get the following error messages:

Docker Client:

FATA[0009] Error response from daemon: invalid registry endpoint https://d.mydomain.com/v2/: https://d.mydomain.com/v2/ does not appear to be a v2 registry endpoint. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry d.mydomain.com` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/d.mydomain.com/ca.crt

Docker Daemon:

ERRO[0057] Handler for POST /auth returned error: invalid registry endpoint https://d.mydomain.com/v2/: https://d.mydomain.com/v2/ does not appear to be a v2 registry endpoint. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry d.mydomain.com` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/d.mydomain.com/ca.crt
ERRO[0057] HTTP Error: statusCode=500 invalid registry endpoint https://d.mydomain.com/v2/: https://d.mydomain.com/v2/ does not appear to be a v2 registry endpoint. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry d.mydomain.com` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/d.mydomain.com/ca.crt

So I try adding --insecure-registry d.mydomain.com to:

  • /etc/default/docker with DOCKER_OPTS= -H unix:///var/run/docker.sock --insecure-registry d.mydomain.com
  • the arguments of starting docker manually with docker -d --insecure-registry d.mydomain.com

neither of these, or any other I have found online, work. Each time, after restarting docker and attempting to log in again gives me the same error message.

A few other things I have tried:

  • In a browser going to d.mydomain.com results in a 404
  • In a browser going to d.mydomain.com/v2/ results in: {}
  • Replacing https://d.mydomain.com/v2/ in the login command with all of these with no success
    • http://d.mydomain.com/v2/
    • d.mydomain.com/v2/
    • http://d.mydomain.com/
    • d.mydomain.com/

This setup with HAProxy doing the SSL termination and HTTP auth has worked in the past using the first version of the registry and older versions of docker. So has anything in Docker registry v2 changed? Does this still work? If it hasn't changed, why won't the --insecure-registry flag do anything anymore?

Also, I have been working on getting this working for a while so I may have forgotten all the things I have tried. If there is something that may work, let me know and I will give it a try.

Thanks, JamesStewy


Edit

This edit has been moved to the answer below

like image 302
JamesStewy Avatar asked May 19 '15 05:05

JamesStewy


1 Answers

I have got it working. So here is my new config:

haproxy.cfg

global
    chroot /var/lib/haproxy
    user haproxy
    group haproxy
    daemon
    tune.ssl.default-dh-param 2048

userlist auth_list
    group docker_registry users root
    user root password ***PASSWORD***

backend docker-registry
    server 127.0.0.1:5000_localhost 127.0.0.1:5000 cookie 127.0.0.1:5000_localhost 

backend docker-registry-auth
    errorfile 503 /path/to/registry_auth.http

frontend shared-frontend
    mode http
    bind *:80
    bind *:443 ssl crt *** CERT FILES ***
    option accept-invalid-http-request

    acl domain_d.mydomain.com hdr(host) -i d.mydomain.com
    redirect scheme https if !{ ssl_fc } domain_d.mydomain.com
    acl auth_docker_registry_root http_auth(auth_list) root
    use_backend docker-registry-auth if !auth_docker_registry_root { ssl_fc } domain_d.mydomain.com
    rsprep ^Location:\ http://(.*) Location:\ https://\1
    use_backend docker-registry if domain_d.mydomain.com

registry_auth.http

HTTP/1.0 401 Unauthorized
Cache-Control: no-cache
Connection: close
Content-Type: text/html
Docker-Distribution-Api-Version: registry/2.0
WWW-Authenticate: Basic realm="Registry"

<html><body><h1>401 Unauthorized</h1>
You need a valid user and password to access this content.
</body></html>

The differences being the http-request auth line has been replaced with use_backend docker-registry-auth. The backend docker-registry-auth has no servers to it will always give a 503 error. But the 503 error file has been changed to registry_auth.http. In registry_auth.http the error code is overridden to 401, the header WWW-Authenticate is set to Basic realm="Registry", the basic HAProxy 401 error page is supplied and, most importantly, the header Docker-Distribution-Api-Version is set to registry/2.0.

As a result this hacky work-around setup works exactly the same as the old http-request auth line except the custom header Docker-Distribution-Api-Version is now set. This allows this set up to pass the test which starts on line 236 of https://github.com/docker/docker/blob/v1.7.0/registry/endpoint.go.

So now when I run docker login d.mydomain.com, login is successful and my credentials are added to .docker/config.json.

The second issue was that I couldn't push to the new repository even through it logged in. This was fixed by adding the rsprep line in the frontend. What this line does is modify the Location header (if it exists) to turn all http:// to https://.

I also found this bit of documentation for future reference.

like image 99
JamesStewy Avatar answered Nov 17 '22 13:11

JamesStewy