(1 votes, average: 1.00 out of 5)
Loading...
Creating your own private Docker Registry using a Self Signed Certificate
Creating your own private Docker Registry without authentication, authorization or SSL can be a simple process, but creating a private Docker Registry with SSL support, authentication i.e. Tokens, LDAP, etc.. can be a bit more complicated. Below I will show you in detail how to create your own private Docker Registry(v2), as well as a number of issues and workarounds. to note, all tests ware completed / tested o ubuntu 17.04(zesty) OS. Creating your own Docker Registry, requiters addressing a number of issues outlined below. Most of them are addressed later in this article, and some will be addressed in an upcoming article. Securing your Docker Private Registry Instance(s), includes- Option 1: Configure Your own CA with your SSL Certificate
- Option 2: Buy an SSL Certificate from one of the public providers
- Use Simple SSH port forwarding
- Use pre-configured Nginx Containers to front end your Docker Registry
- Create your own Nginx Container to protect your Docker Registry
- Use a hardware Load Balancer such as F5 to front-end and protect your Docker Registry
- Use a pre-configured Docker container with all the Docker Registry + LDAP configurations
- Use a Docker Token service for Authentication and Authorization (works in newer Docker versions)
Setting / configuring your Docker Proxy settings
Note: You can skip this step if you are not using a proxy i.e. if you are not using http_proxy, https_proxy, etc… The below configuration is an example of my /etc/systemd/system/docker.service.d/http-proxy.conf file with the proxy configuration in it.[Service] Environment="HTTP_PROXY=http://proxy.domain.com:3127/" Environment="HTTPS_PROXY=http://proxy.domain.com:3127/" Environment="http_proxy=http://proxy.domain.com:3127/" Environment="https_proxy=http://proxy.domain.com:3127/" Environment="NO_PROXY=localhost,127.0.0.1,docker,docker.domain.com" Environment="no_proxy=localhost,127.0.0.1,docker,docker.domain.com"Note: Make sure to add your local hostname, in this case its docker to your no_proxy list. I was struggling with this for a while by not having that set. if you do not add your hostname to the no_proxy list, your docker iptables related configuration will not get properly configured, the resutls will be, not being able to access your private docker repository. to note, your localhost:5000 might still work(if no SSL is enabled), but with SSL enabled using an FQDN (like docker.domian.com) is required, which will not work otherwise. Below are the errors you might get while pushing an image to the local registry, without adding your hostname to the no_proxy list.
# Error while pushing an image to the local repository. docker push docker.domain.com:5000/alpine The push refers to a repository [docker.domain.com:5000/alpine] Get https://docker.domain.com:5000/v1/_ping: Forbidden # Docker push working as expected. docker push docker.domain.com:5000/alpine The push refers to a repository [docker.domain.com:5000/alpine] e154057080f4: Layer already exists latest: digest: sha256:c0537ff6a5218ef531ece93d4984efc99bbf3f7497c0a7726c88e2bb7584dc96 size: 528
Creating and Configuring your Certificates
Next, will move on creating your Certificates – this is needed for SSL communication. There are a number of methods to use/create your own certificates, below is outlined two options. Note You can of course use/get your SSL certificate signed by one of the public CA’s, you can then skip to the next step.- Manuel creating your certificate and move it in place
- Automatically creating your certificate and move it in place, using the paulczar/omgwtfssl Docker image
Creating your own Certificates – The Manuel way
As mentioned above, I am using the FQDN i.e. hostname as docker I will use this for the rest of the article.First create a CA key with a bit size of 2048 (or whatever bit length you like)
openssl genrsa -out ca-key.pem 2048
Sign your CA key
openssl req -x509 -new -nodes -key ca-key.pem -days 3650 -out ca.pem -subj '/C=US/ST=NY/L=NY/O=devtech101.com/CN=docker.domain.com'
Next, Create a server / client certificate and sign with ca
First lets Generate a new server or client key.openssl genrsa -out key.pem 2048
Create the client certificate request – to be signed by CA
Note: If you like to use one of the public CA’s, the key.pem would be the file send to the public CA for signature.openssl req -new -key key.pem \ -newkey rsa:2048 -nodes \ -subj '/C=US/ST=NY/L=NY/O=devtech101.com/CN=docker.domain.com' \ -outform pem -out key.csr -keyout key-req.pem
Self sign the client certificate by your own CA (or send to public CA)
openssl x509 -req -in key.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial \ -out cert.pem -days 1095 -extensions v3_reqNow, that the certificate(s) are generated(CA and server/client), we are ready to use them. Copy the certificate(s) to the proper locations (outlined below), the docker registry will then use / trust the new certificate(s), more is explained below.
mkdir -p /docker-data/registry/{data,ssl,config} cp ca-key.pem ca.pem ca.srl cert.pem key.csr key.pem /docker-data/registry/ssl/.The process above shows you how to create your certificates manually. Next will move on to show you how to to automate this process(its your choice which direction to go).
Creating your own Certificates by Using the paulczar/omgwtfsslby Docker image
The Docker image used in automating the Certificates – credit goes to this git repository The process below will pull the Docker image and generated the certificate(s) and key(s) (CA and Server/Client).mkdir -p /docker-data/registry/{data,ssl,config} docker run --rm -v /docker-data/registry/ssl:/certs \ -e SSL_IP=10.10.10.10 \ -e SSL_DNS=docker.domain.com \ -e SSL_SUBJECTdocker.domain.com \ -e CA_SUBJECT=docker.domain..com \ -e CA_EXPIRE=1095 \ paulczar/omgwtfssl
Initial Registry Configuration
Next will move on to, Required Docker SSL settings
Below are the the settings required to get the Docker Registry working with SSL.echo "# location of registry data REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/docker-data/registry/data # location of TLK key/cert REGISTRY_HTTP_TLS_KEY=/docker-data/registry/ssl/key.pem REGISTRY_HTTP_TLS_CERTIFICATE=/docker-data/registry/ssl/cert.pem # location of CA of trusted clients REGISTRY_HTTP_TLS_CLIENTCAS_0=/docker-data/registry/ssl/ca.pem" > /docker-data/registry/config/registry.envNote: Additional options can be set in the registry.env(depending in the Docker version, RedHat, Ubuntu, etc), I included a small subset sample below.
# The Docker registry configuration file (this file) DOCKER_REGISTRY_CONFIG=/docker-data/registry/config/registry.env # The configuration to use from DOCKER_REGISTRY_CONFIG file SETTINGS_FLAVOR=local # Address to bind the registry to REGISTRY_ADDRESS=0.0.0.0 # Port to bind the registry to REGISTRY_PORT=5000 # Number of workers to handle the connections GUNICORN_WORKERS=4
Add and trust the self signed certificate(s) on your system
The next step is to add your own CA certificate to the systems trusted certificates store. Lets create a Docker directory to store our Docker CA certificate, then lets add the certificate location to system CA trusted store.if ! test -d /usr/share/ca-certificates/docker ; then mkdir -p /usr/share/ca-certificates/docker ;fi if ! grep -w docker/ca.pem /etc/ca-certificates.conf ; then echo "docker/ca.pem" >>/etc/ca-certificates.conf ;fiNext, lets copy the CA certificate to the new trusted store location we just created, then run the system update, to let the system know about the new certificate.
cp /docker-data/registry/ssl/ca.pem /usr/share/ca-certificates/docker/ca.pem update-ca-certificatesLast, restart the Docker demon for the changes to take effect.
/etc/init.d/docker restartNote: Restarting Docker is absolutely needed, as the self signed certificate will not work without that. Below are the errors you might get, if you do not restart the Docker demon even after you added your new SSL certificate(s).
# Error while trying to push an image docker push docker.domain.com:5000/alpine The push refers to a repository [docker.domain.com:5000/alpine] Get https://docker.domain.com:5000/v1/_ping: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "docker.domain.com") # Error while trying to pull an image docker pull docker.domain.com:5000/alpine Error response from daemon: Get https://docker.domain.com:5000/v1/_ping: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "docker.domain.com")
Complete the Docker registry installation and configuration
Now, finally complete docker initial registry installation and configuration.docker run -d \ --name registry \ -p 5000:5000 --restart always \ -v /docker-data/registry:/opt/registry \ --env-file /docker-data/registry/config/registry.env \ registryYou can also create a DockerFile with similar options like the one below.
FROM registry:latest # Add the below for Docker v1 to be able to use the search uri. ENV SEARCH_BACKEND sqlalchemy ENV SQLALCHEMY_INDEX_DATABASE sqlite://///docker-data/registry/data/docker-registry.db ENV STORAGE_PATH /docker-data/registry CMD exec docker-registryThen build and run the Docker registry container.
# Build the registry container. docker build -t registry . # Start the Docker registry. docker run -d -p 5000:5000 \ -v /docker-data/registry:/opt/registry \ --env-file /docker-data/registry/config/registry.env
Begin using your own Docker registry
Now that the registry is up and running, we can start pushing and pulling images. Lets pull the busybox image from the public repository.docker pull busyboxBefore we can publish/push the busybox image we now need to tag it.
# Tag the busybox image docker tag alpine docker.domain.com:5000/busybox:devtech1 # Push the busybox image our private repository docker push docker.domain.com:5000/busybox:devtech1Last, lets try to pull the image from our own repository.
docker pull docker.domain.com:5000/busybox:devtech1
Authentication and Authorizations
Now that our private repository is up and running, its time to discuses Docker security options. Note: The private Docker registry configured above has no security configurations configured, i.e. you can push/pull withany Authentication required. There are a number of options around Docker Authentication and Authorizations, from using Docker itself, using tokens, LDAP, etc, front-ending Docker with an Nginx Docker image, or front-ending Docker by using a Load Balancer like an F5 handling the security. Below I will discuss some of the options.Using SSH for simple Authentication
The simplest configuration, i.e. just adding Authentication in the mix can be using ssh port-forwarding. To use that, just run the below, change the port and server names to match your configuration.ssh -N -L 5000:localhost:443 user@docker
Using a Docker pre configured image for Authentication
The next option would be, building an Nginx image, or using a pre-build Nginx Docker images. By using Nginx as the proxy(front-end) for your Docker Registry, you gain all the befits that Nginx brings to table. I hope to update this article once available, with the full details. The next option would be(and especially if you’re looking to utilize your own LDAP), by using one of the Docker images available on github. they include an easy way to configure, point to your own LDAP for Authentication and Authorization. There are a number of images available on github, each with their own benefits (and weaknesses). a partial list is below.- Docker registry front-end – includes LDAP, Token support out of the box
- Using Docker registry with existing LDAP or Active Directory
- Docker Nginx proxy
- Docker Nginx proxy(fork of jwilder) with additional options supported like TLS(SSL), etc
Private Docker registry GUI Managers
Another option is, to use one of the Docker GUI managers, there are a nice few options available, each have their own strengths and weaknesses. Below is a partial Docker Web UI/GUI manager list. Atomic Registry – a Red-hat sponsored project Portus – a Suse sponsored project Harbor – a VmWare sponsored project Shipyard Build on Docker Swarm – Composable Docker Management Other GUI option are, to use something like Rancher and Portainer more details is available hereDisabling SSL temporarily for testing purposes
For troubleshooting purposes, you might try to disable the SSL in your registry. Modify your DOCKER_OPTS in the /etc/default/docker Docker file like below. Note: A docker restart will be required for the changes to take effect.# /etc/default/docker # Disable SSL temporarily DOCKER_OPTS="--dns 8.8.8.8 --ip-masq=true --insecure-registry docker.domain.com:5000" # Enable SSL (the way it shuld normaly be) DOCKER_OPTS="--dns 8.8.8.8 --ip-masq=true" /etc/init.d/docker restart
Private Docker helpful tips
Docker registry v2 searching / tag listing
Docker private registry v2, has no search endpoint, I would love to find out otherwise – please let me know in the comments below. However, their are a few other end-points available to use listed below. Using Docker for Search in v2 will not workdocker search docker.domain.com:5000/busybox Error response from daemon: Unexpected status code 404Using curl will partly work
Getting the full Docker private registry listing
curl -X GET https://docker.domain.com:5000/v2/_catalog {"repositories":["alpine"]}
Getting the tag list for a specific image
curl -X GET https://docker.domain.com:5000/v2/busybox/tags/list {"name":"busybox","tags":["latest"]}
Getting the manifest for a specific image
curl -X GET https://docker.domain.com:5000/v2/busybox/manifests/refrence {"errors":[{"code":"MANIFEST_UNKNOWN","message":"manifest unknown","detail":{"Tag":"refrence"}}]}Note: You can always create your own little Python program to pull the full catalog and tags, adding to a dictionary, then manipulating that. What was your experience creating a private Docker registry, please let me know in the comments below.
Helpful Docker registry information script
The below script will proved details about your private Docker registry packages and disk space.#!/bin/bash REGISTRY_FILESYSTEM_ROOTDIRECTORY="/opt/registry" dockeImgList=`find $REGISTRY_FILESYSTEM_ROOTDIRECTORY -print | \ grep 'v2/repositories' | \ grep 'current' | \ grep -v 'link' | \ sed -e 's/\/_manifests\/tags\//:/' | \ sed -e 's/\/current//' | \ sed -e 's/^.*repositories\// /' | \ sort` echo "$dockeImgList" echo "Number of images: `echo $dockeImgList |wc -l | awk {'print $1'}`" echo "Disk space used: `du -hs $REGISTRY_FILESYSTEM_ROOTDIRECTORY`"A sample output is below.
/tmp/get_docker_info.sh busybox:latest Number of images: 1 Disk space used: 2.1M /docker-data/registryYou might also like Managing docker on Ubuntu 17.04 using Rancher or Portainer Using ZFS for Docker COW Storage layer(s) In Ubuntu 17-04
0
0
votes
Article Rating