Last Updated: January 19, 2018
· ihcsim

Insecure And Self-Signed Private Docker Registry With Boot2Docker

Let's take a look at how to set up an insecure docker registry and a self-signed docker registry on Digital Ocean. Then we will attempt to access the registry via basic authentication with boot2docker.

What I use:

  1. Docker 1.9.0
  2. Docker Machine 0.5.0 (version 1.9.0, build master : 16e4a2a)
  3. Docker Registry 2
  4. Digital Ocean account

Create A Registry Host

To create the registry host on Digital Ocean:

$docker-machine create --driver digitalocean \
  --digitalocean-access-token <our_digitalocean_token> \
  --digitalocean-region <our_region> \

This creates a droplet named registry in <our_region>, defaulted to 512MB of memory and 20GB of hard disk storage, with an auto-assign public floating IP address.

Set Up Docker Registry 2.0

Let's SSH into our droplet and set up a docker registry.

$eval `docker-machine env registry`
$docker-machine ssh registry
root@registry-02:~# docker run -d -p 5000:5000 \
     --restart=always --name registry \
     -v `pwd`/data:/var/lib/registry \

This should get Docker Registry 2.0 running on our host. We can verify this by using docker ps.

If we tried to push a docker image to our registry now, it should fail. (In my case, I am using boot2docker.)

$docker pull isim/consul # pull from docker hub
$docker tag isim/consul <floating_ip>:5000/consul # tag for remote repository
$docker push <floating_ip>:5000/consul # push to my registry
The push refers to a repository [] (len: 1)
unable to ping registry endpoint
v2 ping attempt failed with error: Get tls: oversized record received with length 20527
v1 ping attempt failed with error: Get tls: oversized record received with length 20527

Trust An Insecure Registry

To tell our local Docker to disregard security and trust our docker registry as an insecure registry, make the following changes in our local Docker (not our registry host). In my case, this changes need to be done to my boot2docker.

$docker-machine ssh default #ssh into boot2docker
docker@default:~$ sudo vi /var/lib/boot2docker/profile #update boot2docker profile to trust the insecure registry

Add the floating IP of your registry node to EXTRA_ARGS as an insecure registry in the boot2docker profile file:

    --label provider=virtualbox

Exit out of boot2docker and restart it using docker-machine. Now attempt to push our newly tagged image again, and it should work.

Since we run our registry with a mounted volume earlier, we should see the image stored under the volume source. In my case, my registry host looks like:

root@registry:~# ls -al data/docker/registry/v2/repositories/
total 12
drwxr-xr-x 3 root root 4096 Nov 29 19:37 .
drwxr-xr-x 4 root root 4096 Nov 29 19:37 ..
drwxr-xr-x 5 root root 4096 Nov 29 19:38 consul

Please read up on the pros-and-cons of insecure registry.

Self-Signed Registry With Access Restriction

Remove the --insecure-registry flag from our boot2docker profile file and restart our boot2docker. We will now create our own self-signed certificate, secure our registry with TLS, and then restrict access to it using Basic Auth.

To generate a self-signed certificate on our registry host:

root@registry:~# mkdir certs
root@registry:~# openssl req \
  -newkey rsa:4096 -nodes -sha256 \
  -keyout certs/domain.key \
  -x509 -days 356 \
  -out certs/domain.crt

When prompted for Common Name (e.g. server FQDN or YOUR name), I use <floating_ip> You can read more about here. We should see our private keys and certificates in the certs/ folder.

To set up basic auth on our registry host:

root@registry:~# mkdir auth
root@registry:~# docker run --entrypoint htpasswd registry:2 -Bnb <username> <password> > auth/htpasswd

This will create a auth/htpasswd file.

Stop and remove our running docker registry. (/data folder should still be intact.) Restart it to pick up the certs and password:

docker run -d -p 5000:5000 --restart=always --name registry \
    -v `pwd`/auth:/auth \ 
    -v `pwd`/certs:/certs \
    -v `pwd`/data:/var/lib/registry \
    -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"

Now we have to update the Docker daemon on our boot2docker to trust the certificates.

docker@default:~$ sudo mkdir -p /etc/docker/certs.d/<floating_ip>
docker@default:~$ sudo vi /etc/docker/certs.d/<floating_ip> # copy certificate from registry host to this file

Create the /etc/docker/certs.d/<floating_ip> folder and copy our certs/domain.crt certificate from our registry host to /etc/docker/certs.d/<floating_ip>

Restart our docker daemon.

docker@default:~$ sudo /etc/init.d/docker restart

Now we should be able to push image and login to our registry host.

$docker login <floating_ip>
WARNING: login credentials saved in ~/.docker/config.json
Login Succeeded
$docker tag isim/consul <floating_ip>
$docker push <floating_ip>

Notice the usage of the domain.

4 Responses
Add your response

Great read, it works if using insecure-registry.
But failed using Self-Signed cert, error msg: 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/host:port/ca.crt

However it succeeded if using curl to access using the cert.
sudo curl --cacert /etc/docker/certs.d/host:port/ca.crt https://user:pass@host:port/v2

Any ideas please? thanks

over 1 year ago ·

BTW: I'm using docker version 1.9.1, never succeeded neither on mac nor on linux.

over 1 year ago ·

@gembinz I haven't seen that error before. May have to google the error to see what's going wrong. If you are able to curl the endpoint, does that mean the registry container is up and running?

over 1 year ago ·

Adding the insecure registry flag was something that I was stuck with for a long time. Thanks for this post and it saved my day!! :)

over 1 year ago ·