skip to Main Content

I have an ordinary ubuntu image with no dockerd installed, only the docker command line client and curl are installed such that I can query a docker registry. I have set up tls security. The following works as expected.

curl https://myregistry/v2/_catalog # gets the info
curl http://myregistry/v2/_catalog  # fails as expected

So I am confident that docker can pull from the registry via https. Unfortunately and in contradiction to the documentation, my docker client only tries http, which of course fails.

docker pull myregistry/myimage
Using default tag: latest
Error response from daemon: Client sent an HTTP request to an HTTPS server.

The Ubuntu image and the registry/2 are the newest available versions as of EOY 2024.

My question is how to tell docker pull to use https instead of http? All posts I found so far describe the opposite problem where docker talks https to an http registry.

I assume that my certificates are correct, because otherwise curl would have failed with both http and https. The certificates and keys are in /etc/docker/certs.d/registry i.e. (ca.crt, myregistry.pem and myregistry.key )

2

Answers


  1. Chosen as BEST ANSWER

    Curl on the client container connects to the registry directly. Matters are different with docker pull because in this case the dind container pulls on behalf of the client container. Hence, the client needs to tls authenticate against the dind and not the registry when pulling from the registry. In other words, pulling needs the dind daemon as a middle man while curl does not.

    The other thing that I was missing was the importance of setting --network-alias docker.

    With these two issues in mind I came up with the following command lines to set up a ubuntu container that pulls from a registry container using a dind container.

    registry container (image registry:2)

    docker run -it --rm --network some-network               
       -e REGISTRY_HTTP_ADDR=0.0.0.0:443                     
       -e REGISTRY_HTTP_TLS_KEY=/certs/key.pem               
       -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/cert.pem      
       -v ./volumes/build.lab/certs:/certs:ro                
       --name myregistry --hostname myregistry registry:2
    

    Docker In Docker Container (image docker:dind)

    docker run  
        --privileged -d --network some-network       
        --network-alias docker                       
        -e DOCKER_TLS_CERTDIR=/certs                 
        -v ./volumes/dind/ca-certificates:/usr/local/share/ca-certificates 
        -v ./volumes/dind/ca:/certs/ca               
        -v ./volumes/dind/client:/certs/client       
        -v ./volumes/dind/server:/certs/server       
        --name dind --hostname dind docker:dind
    

    A Mock so I do not have to build Ubuntu for this test (image docker:dind)

    docker run --rm -it --network some-network                        
        --name client --hostname client                               
        -e DOCKER_TLS_CERTDIR=/certs -e DOCKER_HOST=tcp://dind:2376   
        -v ./volumes/dind/client:/certs/client:ro                     
      docker:latest sh
    
    # docker pull myregistry/myimage
    pulling . . . 
    

  2. This is the behavior of you configure the registry as an "insecure registry" in docker. That setting should be visible in docker info, and would commonly be configured in /etc/docker/daemon.json (changes apply when reloading or restarting the docker engine). Remove your registry from this configuration to return to the default TLS connection.

    For more details, see https://docs.docker.com/reference/cli/dockerd/#insecure-registries

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