Private Docker Registry Part 4: let’s secure the registry

Christian Nadeau
2 min readJan 27, 2017

--

Now that we have a registry with authentication and storing docker images to Azure Storage, we need to get this server out on it’s own, meaning we need to secure it with SSL.

NOTES:

The Services Definition

Important Assumption: You are running those docker commands from (or using docker-machine as explained in this article) a machine publicly accessible by the domain you want to get SSL certificates for.

version: '2'
services:
haproxy:
image: m21lab/haproxy:1.6.2
links:
- letsencrypt
volumes_from:
- letsencrypt
letsencrypt:
image: m21lab/letsencrypt:1.0
environment:
DOMAINS: 'YOUR_DOMAIN'
EMAIL: 'RECOVERYEMAIL@YOUR_DOMAIN'
OPTIONS: '--staging'
registry:
volumes_from:
- letsencrypt:ro
environment:
REGISTRY_HTTP_SECRET: "your-http-secret"
REGISTRY_HTTP_TLS_CERTIFICATE: /etc/letsencrypt/live/LETSENCRYPT_DOMAINS_ENV_VAR/fullchain.pem
REGISTRY_HTTP_TLS_KEY: /etc/letsencrypt/live/LETSENCRYPT_DOMAINS_ENV_VAR/privkey.pem
registry-ui:
environment:
FORCE_SSL: 'true'
ENV_REGISTRY_PROXY_FQDN: 'LETSENCRYPT_DOMAINS_ENV_VAR'
ENV_DOCKER_REGISTRY_USE_SSL: 1

Service Overrides

HAProxy

  • Uses a different image which will be handling the SSL traffic.
  • Links to the new letsencrypt service to route the challenges http requests to it
  • Uses volumes_from letsenrypt service to read the received SSL certificates and dynamically load them

Let’s Encrypt

This services is used to generate valid CA signed SSL certificates for the domain hosting the registry. More information in the previous article

Registry

This service is the docker registry. A lot of configuration was required:

  • Uses volumes_from letsenrypt service to read the received SSL certificates and dynamically load them
  • Set registry service specific environment variables:
    REGISTRY_HTTP_SECRET=secret: A randomly generated secret used to sign state that may be stored. More information about it here
    REGISTRY_HTTP_TLS_CERTIFICATE=public key
    REGISTRY_HTTP_TLS_KEY=private key:

    Those must be mapped to the letsencrypt service volume

Registry UI (Docker Registry Frontend)

This service hosts a very simple docker UI name docker-registry-frontend by Konrad Kleine (thanks a lot!). In this service, not so much was required to be configured:

  • Set the registry-ui environment variables:
    FORCE_SSL=true: To make sure all the traffic redirected from the haproxy service is using SSL
    ENV_REGISTRY_PROXY_FQDN=“DOMAIN”
    : The domain name you want to be displayed in the registry UI.
    ENV_DOCKER_REGISTRY_USE_SSL=1: The registry must now be accessed using https

How to start it

To start the registry, from your domain accessible machine or using docker-machine to point your local docker environment to a domain accessible machine, simply run this command

docker-compose -f docker-compose.yml \
-f docker-compose.auth.yml \
-f docker-compose.azure.yml \
-f docker-compose.ssl.yml \
up -d
  • The registry is reachable at DOMAIN:5000
  • The registry UI is reachable https://DOMAIN, you’ll be asked for a password

IMPORTANT NOTES: The registry is:

  1. Running on your domain
  2. Authenticated using basic auth
  3. Storing all images in the Azure Storage Account you specified
  4. Using SSL

How to validate it works

Since we already pushed an image to the local repository once we setup the Azure Storage Account, this image is still there. We can pull it using the domain instead of local host to login/pull/logou

docker login -u <username> DOMAIN:5000
# enter your password
docker pull DOMAIN:5000/<optional-username>/alpine:3.4docker logout DOMAIN:5000

We hope this series of articles helped you!

--

--