Docker: how to create a private registry
Scenario: We need a private docker registry for our custom images, the registry needs to use SSL.
Architecture
- registry-server: A server with docker installed that will act as private registry, runs under user docker_user.
- docker-server: A server with docker installed that will act as a docker client to push and pull images, runs under user docker_user.
Solution
Create registry credentials
Login to registry-server and enter the following to create a path that will hold the password of docker_user, a user that the docker-server will use to authenticate.
$ mkdir -p ~/registry/auth
Create the password for docker_user
$ docker run --entrypoint htpasswd registry:2.7.0 -Bbn docker_user docker_password > ~/registry/auth/htpasswd
SSL Certificate
Now we will create a directory that will hold the SSL certificate
$ mkdir -p ~/registry/certs
The certificate that we will create will be a self-signed, of course you can use a signed one.
$ openssl req -newkey rsa:4096 -nodes -sha256 -keyout ~/registry/certs/domain.key -x509 -days 365 -out ~/registry/certs/domain.crt
You will need to answer some questions, the important one is the FQDN one, this should be the FQDN of the registry server.
Run the registry container
Run the registry container, the registry its self is a container that we can pull from dockerhub.
$ docker run -d -p 443:443 --restart=always --name registry \ -v /home/docker_user/registry/certs:/certs \ -v /home/docker_user/registry/auth:/auth \ -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \ -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \ -e REGISTRY_AUTH=htpasswd \ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ registry:2.7.0
Registry Verification
If everything gone well the registry container should start on the background, to verify that it functions we will do a test, run this from the shell of the registry server.
$ curl -k https://localhost:443
It should return nothing as output! lets verify the exit code of curl as well
$ echo $?
0
If the output is 0 then curl exited without any error.
Configure docker client
We need to create the directory that will hold the public SSL certificate and copy it from the registry-server.
$ sudo mkdir -p /etc/docker/certs.d/registry-server:443
$ sudo scp docker_user@registry-server:/home/docker_user/registry/certs/domain.crt /etc/docker/certs.d/registry-server:443
Now we need to allow docker-server to login to insecure registries, this is because we have selected to use an signed by an unknow authority certificate and this is considered as a possible security risk.
$ sudo vim /etc/docker/daemon.json
Enter and save
{
"insecure-registries" : ["registry-server:443"]
}
Login private registry
From the docker-server enter
$ docker login registry-server:443
It will ask for a username and password, use docker_user and docker_password
You should see a message indicating that “Login Succeeded”
Push an image to registry-server
To push an image to the registry-server we need to create a new one in docker-server, lets pull an existing one to docker-server
$ docker pull ubuntu
This will download the ubuntu image from the public dockerhub registry
Lets do a tag modification to the ubuntu image
$ docker tag ubuntu registry-server:443/my-test:1
Push the image to the private registry
What we did before is that we changed the tag of an existing image, now we can push this image to registry-server, our private registry.
$ docker push registry-server:443/my-test:1
Push the image from the private registry
Now, lets pull the image we just pushed to the registry-server back to docker-server, to do this we need to delete the ubuntu and the modified image from docker-server.
$ docker image rm registry-server:443/my-test:1
$ docker image rm ubuntu:latest
$ docker pull registry-server:443/my-test:1
Now executing docker images will show the image we just pulled from the registry-server.