Skip to main content

Docker Private Registry 2.0

Quick Notes on setting up Docker Private Registry with TLS (secure), shout out to bobcares.com as I'm basically cannibalizing their notes with my edits because they've already written out some great notes, just tailoring it to my own situation.

Generate SSL via container

create working directories:

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

(optional) if you have selinux running, you need to change permissions on your registry directory

chcon -Rt svirt_sandbox_file_t <registry_dir>

replace the 'SSL_SUBJECT' with your own and run this command to generate your SSL files

docker run --rm -v /opt/registry/ssl:/certs -e SSL_SUBJECT=registry.docker-repo.net paulczar/omgwtfssl

Native Basic Auth

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

Add new Certificate Authority (CA)

your registry clients need to recognize the CA when it connects to the registry so you need to install that CA on your client machines. e.g.

[root@registry]$ scp /var/opt/registry/ssl/ca.pem user@other-host:~/
[user@other-host]$ mkdir -p /etc/docker/cert.d/registry:5000/
[user@other-host]$ cp ca.pem /etc/docker/cert.d/registry:5000/

Install the ca-certificates package: yum install ca-certificates Enable the dynamic CA configuration feature: update-ca-trust force-enable retart docker systemctl restart docker

Registry 'config.yml'

needed to configure registry within the container:

version: 0.1
log:
fields:
service: registry
storage:
delete:
enabled: true
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
Access-Control-Allow-Origin: ['http://dockeregistry.darksyde']
Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS', 'DELETE']
Access-Control-Allow-Headers: ['Authorization,Credentials']
Access-Control-Max-Age: [1728000]
Access-Control-Allow-Credentials: [true]
Access-Control-Expose-Headers: ['Docker-Content-Digest']
auth:
htpasswd:
realm: basic-realm
path: /auth/htpasswd
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3

Docker compose your image with SSL

docker-compose file for the cert generating image:

# docker trusted registry (private) compose

registry:
restart: always
image: registry:2
container_name: registry2
ports:
- 5000:5000
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/opt/registry/data
REGISTRY_HTTP_TLS_CERTIFICATE: /var/opt/registry/ssl/cert.pem
REGISTRY_HTTP_TLS_KEY: /var/opt/registry/ssl/key.pem
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
volumes:
- /var/opt/registry:/var/opt/registry
- /var/opt/registry/auth:/auth
- /var/opt/registry/config/config.yml:/etc/docker/registry/config.yml

Run docker-compose

if all the files are in place and the CA is installed on all client hosts, you should be able to run:

[root@registry /var/opt/registry ]$ docker-compose up -d

check our registry container is running:

[root@dockeregistry registry]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a60a47bcad92 registry:2 "/entrypoint.sh /etc/" 26 minutes ago Up 1 seconds 0.0.0.0:5000->5000/tcp registry2

from a client host (i.e. a host that needs to talk to the registry and has the CA added to it) try

logging in

[root@docker certs.d]# docker login http://dockeregistry.darksyde.net:5000
Username (usertest):
Password:
Login Succeeded

now try and pull an image, tag it with our private registry and push it

pull

[root@docker ~]# docker pull ubuntu:16.04
Trying to pull repository docker.io/library/ubuntu ...
16.04: Pulling from docker.io/library/ubuntu
ae79f2514705: Pull complete
5ad56d5fc149: Pull complete
170e558760e8: Pull complete
395460e233f5: Pull complete
6f01dc62e444: Pull complete
Digest: sha256:506e2d5852de1d7c90d538c5332bd3cc33b9cbd26f6ca653875899c505c82687

tag

[root@docker ~]# docker tag ubuntu:16.04 dockeregistry.darksyde.net:5000/myubuntu

push

[root@docker ~]# docker push dockeregistry.darksyde.net:5000/myubuntu
The push refers to a repository [dockeregistry.darksyde.net:5000/myubuntu]
49907af65b0a: Pushed
4589f96366e6: Pushed
b97229212d30: Pushed
cd181336f142: Pushed
0f5ff0cf6a1c: Pushing [=========================================> ] 101.9 MB/122 MB
...
latest: digest: sha256:550f6e26da4b4cb8655a96dd6458ea01e2fb3dcb99d24e6dc427c08ea42c9785 size: 1357

SUCCESS!

Troubleshooting

Proxy Matters

if you're behind a proxy vim /etc/sysconfig/docker and add your proxy settings for docker if there's no internet connection from the box

# PROXY
HTTP_PROXY='http://proxy.darksyde.net:80'
HTTPS_PROXY='http://proxy.darksyde.net:80'
NO_PROXY='dockeregistry.darksyde.net'

note: if you dont specify the 'no_proxy' you wont be able to push to your private registry because the request gets routed through the HTTP_PROXY.

Error generating ssl

Digest: sha256:486c1ebae77f9d8b39ab1943fcf98d91f9c48610c9e471010a1ea53df47713ee
----------------------------
| OMGWTFSSL Cert Generator |
----------------------------

--> Certificate Authority
====> Generating new CA key ca-key.pem
ca-key.pem: Permission denied
139662982777740:error:0200100D:system library:fopen:Permission denied:bss_file.c:402:fopen('ca-key.pem','w')
139662982777740:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:404:
====> Generating new CA Certificate ca.pem
Error opening Private Key ca-key.pem
139862407768972:error:02001002:system library:fopen:No such file or directory:bss_file.c:402:fopen('ca-key.pem','r')
139862407768972:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:404:
unable to load Private Key

check SELINUX

ausearch -m avc -ts today | audit2allow

set rule to allow,

before :

[root@dockeregistry opt]# ls -ltrZ registry/
drwxr-xr-x. root root unconfined_u:object_r:var_t:s0 ssl
drwxr-xr-x. root root unconfined_u:object_r:var_t:s0 data
drwxr-xr-x. root root unconfined_u:object_r:var_t:s0 config

run command on your 'registry' folder (or where the docker image is going to write to host filesystem)

[root@dockeregistry opt]# chcon -Rt svirt_sandbox_file_t registry/

after :

[root@dockeregistry opt]# ls -ltrZ registry
drwxr-xr-x. root root unconfined_u:object_r:svirt_sandbox_file_t:s0 ssl
drwxr-xr-x. root root unconfined_u:object_r:svirt_sandbox_file_t:s0 data
drwxr-xr-x. root root unconfined_u:object_r:svirt_sandbox_file_t:s0 config

SUCCESS:

----------------------------
| OMGWTFSSL Cert Generator |
----------------------------

--> Certificate Authority
====> Generating new CA key ca-key.pem
Generating RSA private key, 2048 bit long modulus
...........+++
..................................+++
e is 65537 (0x10001)
====> Generating new CA Certificate ca.pem
====> Generating new config file openssl.cnf
====> Generating new SSL KEY key.pem
Generating RSA private key, 2048 bit long modulus
.................................................................+++
..............................................................................................................................................+++
e is 65537 (0x10001)
====> Generating new SSL CSR key.csr
====> Generating new SSL CERT cert.pem
Signature ok
subject=/CN=dockeregistry.darksyde.net
Getting CA Private Key
====> Complete
keys can be found in volume mapped to /certs

====> Output results as YAML
...
...
...

See Redhat documentation for more info on svirt_sandbox_file_t

Expired ca.crt

check ca.crt for expiry:

openssl x509 -in /etc/docker/cert.d/<registry>/ca.crt -text -noout

docker login failed - bad certificate

on the client you get this error logging in:

[root@docker ~]# docker login http://dockeregistry.darksyde.net:5000
Username: usertest
Password:
Error response from daemon: Get https://dockeregistry.darksyde.net:5000/v1/users/: x509: certificate signed by unknown authority

you check on the registry host with docker logs -f registry2 and see this:

2017/10/13 07:58:07 http: TLS handshake error from 172.16.20.10:33562: remote error: tls: bad certificate
2017/10/13 07:58:07 http: TLS handshake error from 172.16.20.10:33564: remote error: tls: bad certificate

usually means the host calling the registry does NOT recognize the CA of the registry.

the ca.pem from the step above ("Generate SSL via container") needs to be on EVERY HOST that needs to talk to the registry e.g. if your registry is called 'dockeregistry' you'd need to find ca.crt in /etc/docker/certs.d/dockeregistry:5000 (includes ':5000')

note

The directory in '/etc/docker/cert.d/' must match the name of the registry you're logging into - if the registry is "docker.registry.org:6000" the directory must be EXACTLY '/etc/docker/cert.d/docker.registry.org:6000'**