skip to Main Content

All I would like to do is control the top endpoint (MY_ENDPOINT where users will login and pull images. The registry and containers are being hosted (DOCKER_SAAS), so all I need is a seemingly simple redirect. Concretely, where you would normally do:

docker login -u ... -p ... DOCKER_SAAS
docker pull DOCKER_SAAS/.../...

I would like to allow:

docker login -u ... -p ... MY_ENDPOINT
docker pull MY_ENDPOINT/.../...

And even more optimally I would prefer:

docker login MY_ENDPOINT
docker pull MY_ENDPOINT/.../...

where the difference in the last item is that the endpoint contains a hashed version of the username and password, which is set into an Authorization header (using Basic) – so the user doesn’t even need to worry about username and password, just their URL. I’ve tried a proxy_pass as we are already doing for basic packaging (using HTTPS), but that fails with a 404 (in part because we do not handle /v2 – do I need to redirect that through, also?). This led me to https://docs.docker.com/registry/recipes/nginx/, but this seems to only be pertinent if you are hosting the registry. Is what I am trying to do even possible?

2

Answers


  1. This simple config works both with GitHub and Amazon ECR:

    server {
        listen 80;
        server_name localhost;
    
        location / {
            proxy_set_header Authorization "Basic ${NGINX_AUTH_CREDENTIALS}";
            proxy_pass https://registry.example.com;
        }
    }
    

    ${NGINX_AUTH_CREDENTIALS} is a placeholder for actual hash that Docker uses to authenticate. You can get it from $HOME/.docker/config.json after using docker login once:

    {
        "auths": {
            "registry.example.com": {
                "auth": "THIS STRING"
        }
    }
    

    Since proxy injects/replaces authentication header, there is no need to use docker login, just pull using the address of the proxy instead of registry address.

    Why 404?

    I had several 40X errors trying to test the proxy to GitHub with curl:

    • bad credentials – 404, not 401 or 403 as it normally is.
    • GET /v2/_catalog – 404 (not supported on GitHub yet, in backlog). Use GET /v2/repo_name/image_name/tags/list instead.
    • curl without -XGET – 405, it gives response anyway but to get 200 you need to explicitly use GET (-XGET)

    Despite all that docker pull worked flawlessly from the beginning, so I recommend using it for testing.

    How to handle /v2/

    location / matches everything, including /v2/, so there is no particular need for that in proxy.

    Login or Signup to reply.
  2. It sounds like there is also an Nginx or similar reverse-proxy-server in front of the DOCKER_SAAS. Does the infrastructure look like this?

    [MY_ENDPOINT: nginx]  <--> ([DOCKER_SAAS ENDPOINT: ?] <--> [DOCKER_REGISTRY])
    

    My guess is that since the server [DOCKER_SAAS ENDPOINT: ?] is apparently configured with a fixed domain name, it expects exactly that domain name in the request header (e.g. Host: DOCKER_SAAS.TLD). So the problem is probably that when proxying from [MY_ENDPOINT: nginx] to [DOCKER_SAAS ENDPOINT: ?] the wrong Host header is sent along, i.e. by default the host header MY_ENDPOINT.TLD is sent along, but it should be DOCKER_SAAS.TLD instead. E.g.:

    upstream docker-registry {
      server DOCKER_SAAS.TLD:8443;
    }
    
    server {
      ...
      server_name MY_ENDPOINT.TLD;
    
      location / {
        proxy_pass https://docker-registry/;
        proxy_set_header Host DOCKER_SAAS.TLD; # set the header explicitly
        ...
      }
    }
    

    or

    server {
      ...
      server_name MY_ENDPOINT.TLD;
    
      location / {
        proxy_pass https://DOCKER_SAAS.TLD:8443/;
        proxy_set_header Host DOCKER_SAAS.TLD; # set the header explicitly
        ...
      }
    }
    

    Regarding this:

    And even more optimally I would prefer: docker login MY_ENDPOINT

    This could be set on the proxy server ([MY_ENDPOINT: nginx]), yes. (The Authorization: "Basic ..." can be dynamically filled with the respective token extracted from the MY_ENDPOINT, and so on). However, the docker CLI would still ask for a username and password anyway. Yes, the user can enter dummy values (to make the CLI happy), or this would also work though:

    docker login -u lalala -p 123 MY_ENDPOINT
    

    But this would be inconsistent, and would rather confuse the users, imho. So better let it be…

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search