Skip to main content

Docker Trusted Registry (private) 1.0

I wanted to setup a Docker Trusted Registry for my lab, so I did a search and walked through a few tutorials before landing on this one which 'mostly' worked for me:

This is basically my (abbreviated) walk-through of that with the troubleshooting steps

create storage location#

mkdir -p /opt/registry/{data,ssl,config}

create TLS certs, keys using a special-purpose container#

docker run --rm -v /opt/registry/ssl:/certs -e SSL_SUBJECT=<FQDN-of-your-registry-host> paulczar/omgwtfssl

find your files in ''/opt/registry/ssl' (ca-key.pem, ca.pem,, cert.pem, key.csr, key.pem, openssl.cnf)

note: the bobcares guys go with a registry.env file to define their registry config.yml but I decided to go a different way.

setup your native basic auth#

docker run --entrypoint htpasswd registry:2 -Bbn usertest userpasswd > auth/htpasswd

create and run registry container#

[[email protected] registry]$ docker-compose up -dCreating registry ...Creating registry ... done

check its running and test your login:#

[[email protected] registry]# docker psCONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES60cf3aae3d83        registry:2          "/ /etc/"   37 seconds ago      Up 35 seconds>5000/tcp   registry
[[email protected] ~]# docker login https://dockeregistry:5000Username: usertestPassword:Login Succeeded

test the API:

curl -k -u usertest:userpasswd -X GET https://dockeregistry:5000/v2/_catalog

(if you get an UNAUTHORIZED error here, see the 'troubleshooting' section below)

time to test its working for storing our images!#

pull, tag, push#

[[email protected] ~]# docker pull pythonUsing default tag: latestTrying to pull repository ...latest: Pulling from
ef0380f84d05: Pull complete24c170465c65: Pull complete4f38f9d5c3c0: Pull complete4125326b53d8: Pull complete35de80d77198: Pull completeee2411f41489: Pull complete887347005f96: Pull complete9afc04448f28: Pull completeDigest: sha256:cbab919d1fe9f619f5f7d55b852bc04ba661c27abb4db90b802df40287e0f541
[[email protected] ~]# docker tag 41397f4f2887 dockeregistry:5000/python[[email protected] ~]# docker push dockeregistry:5000/pythonThe push refers to a repository [dockeregistry:5000/python]e95f4a878d0c: Pushed7cd56c69527f: Pushedca8fcddadb39: Pushing [===============================================>   ] 59.26 MB/61.89 MB201187968504: Pushedecf5c2e2468e: Pushing [=====>                                             ] 33.47 MB/318.7 MBbb07d0c1008d: Pushing [=================>                                 ] 42.44 MB/122.9 MB4902b007e6a7: Pushing [==========================================>        ] 38.14 MB/44.55 MB007ab444b234: Pushing [==================>                                ] 45.04 MB/123.4 MB
[[email protected] ~]# docker tag 41397f4f2887 dockeregistry:5000/python[[email protected] ~]# docker push dockeregistry:5000/pythonThe push refers to a repository [dockeregistry:5000/python]e95f4a878d0c: Pushed7cd56c69527f: Pushedca8fcddadb39: Pushed201187968504: Pushedecf5c2e2468e: Pushedbb07d0c1008d: Pushed4902b007e6a7: Pushed007ab444b234: Pushedlatest: digest: sha256:cbab919d1fe9f619f5f7d55b852bc04ba661c27abb4db90b802df40287e0f541 size: 2007

a quick query of the registry API should show you your newly pushed image:

curl -k -u usertest:userpasswd -X GET https://dockeregistry:5000/v2/_catalog

and now you can go grab a muffin cos you're FINISHED =)

systemd (OPTIONAL)#

if you're wanting to have a nice clean startup process for your registry, you can do follow this systemd setup.

$ vim /usr/lib/systemd/system/docker.trusted.registry.service

[Unit]Description=Docker Trusted Registry[email protected]After=docker.service
[Service]Restart=alwaysExecStart=/usr/bin/docker start -a registryExecStop=/usr/bin/docker stop -t 60 registry

$ systemctl enable docker.trusted.registry $ systemctl start docker.trusted.registry


cos shit never goes right the first time

error: "code":"UNAUTHORIZED","message":"authentication required"#

[[email protected] registry]# curl -k -u usertest:userpasswd -X GET https://dockeregistry:5000/v2/_catalog{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"registry","Class":"","Name":"catalog","Action":"*"}]}]}


check your htpasswd is setup (properly), and check registry logs (docker logs -f registry) for errors.

error: x509: certificate signed by unknown authority#

[[email protected] ~]# docker push dockeregistry:5000/ubuntuThe push refers to a repository [dockeregistry:5000/ubuntu]Get https://dockeregistry:5000/v1/_ping: x509: certificate signed by unknown authority

fix no.1#

make sure you have the 'ca.crt' in a folder in /etc/docker/certs.d that matches your registry tag exactly (note: you need to do this 'ca.crt' on EVERY host that needs to talk to the registry)

e.g. if your command is docker tag 7b9b13f7b9c0 dockeregistry:5000/ubuntu then you have to have a 'ca.crt' in /etc/docker/certs.d/dockeregistry:5000 (includes colon and port number)

fix no.2#

if fix no.1 doesn't work and you're still getting the 'unknown authority' error try the following from the docker product manual for your distribution.

e.g. I'm on xubuntu so this worked for me (on my laptop):

[email protected]:/usr/local/share/ca-certificates# cp /path/to/dtr/ca.crt .[email protected]:/usr/local/share/ca-certificates# update-ca-certificatesUpdating certificates in /etc/ssl/certs...1 added, 0 removed; done.Running hooks in /etc/ca-certificates/update.d...
Adding debian:ca.pemdone.Updating Mono key storeLinux Cert Store Sync - version local certs with certs from local Linux trust store.Copyright 2002, 2003 Motus Technologies. Copyright 2004-2008 Novell. BSD licensed.
I already trust 176, your new list has 177Certificate added: CN=test-ca1 new root certificates were added to your trust store.Import process completed.Donedone.[email protected]:/usr/local/share/ca-certificates# systemctl restart docker[email protected]:/usr/local/share/ca-certificates# docker login https://dockeregistry:5000Username: usertestPassword:Login Succeeded



random doesnt-fit-anywhere-else note: if you wanted to go HTTP, skip TLS, you need the following in '/etc/default/docker'

# Use DOCKER_OPTS to modify the daemon startup options.DOCKER_OPTS="--insecure-registry <FQDN-of-your-registry-host>:<PORT>"

then restart docker daemon: $ systemctl restart docker