Spekii

Spekii

Monday, April 28, 2014

Your own Docker Registry

A simple post to show how it is simple to deploy your own Docker registry exposed through a HTTPS connection. In order to deploy your own Docker registry you will have to generate a SSL certificate. If you don’t have any access to a CA I suggest you to read the post about how to deploy your own CA. Please note that Docker currently doesn’t support self-signed certificate.

Install docker-registry

git clone https://github.com/dotcloud/docker-registry.git \
/opt/docker-registry

Create your first docker registry config file.

cd /opt/docker-registry
cp config/config_sample.yml config/config.yml

Create some required folders.

mkdir /opt/docker-registry/data

Edit the config, to start we will keep only the common and the dev section, and we will remove a the stuffs related to Google cloud, S3, EC2, to only keep the search backend parameter. So the config should look like this :

common:
    secret_key: _env:SECRET_KEY
    standalone: true

    search_backend: "_env:SEARCH_BACKEND:"
    sqlalchemy_index_database:
        "_env:SQLALCHEMY_INDEX_DATABASE:sqlite://///opt/docker-registry/data/docker-registry.db"

dev:
    storage: local
    storage_path: /opt/docker-registry/data/
    loglevel: debug

Now let’s create protect the registry access by adding a htpasswd file that we will be used by apache2.

htpasswd -c /opt/docker-registry/data/htpasswd <username> <password>

Enable required apache modules.

a2enmod proxy_http
a2enmod ssl
a2enmod headers

The vhost config file of apache2 should be like this :

<VirtualHost *:443>
        ServerAdmin contact@spekii.com
        ServerName docker-registery.spekii.com

        SSLEngine on
        SSLCertificateFile /opt/ssl/docker-registry.crt
        SSLCertificateKeyFile /opt/ssl/docker-registry.key

        CustomLog ${APACHE_LOG_DIR}/access.log combined
        <Location /_ping>
                Satisfy Any
                Allow from all 
        </Location>

        <Location /v1/_ping>
                Satisfy Any
                Allow from all 
        </Location>

        <Location />
                AuthType Basic
                AuthName "Private Docker registery"
                AuthUserFile /opt/docker-registry/data/htpasswd
                Require valid-user
        </Location>

        ProxyPreserveHost  On
        ProxyRequests      Off
        ProxyPass          /  http://127.0.0.1:5000/
        ProxyPassReverse   /  http://127.0.0.1:5000/
        RequestHeader      unset Authorization
</VirtualHost>

First start, first test…

Start the docker-registry processes.

gunicorn --access-logfile /var/log/docker-registry -k gevent \
--max-requests 100 --graceful-timeout 3600 \
-t 3600 -b localhost:5000 -w 8 docker_registry.wsgi:application

Get logged…

docker login https://docker-registry.spekii.com

Username: admin
Password: 
Email: admin@spekii.com
Login Succeeded

Now let’s try to push an image.

docker pull busybox
docker tag busybox docker-registry.spekii.com/busybox
docker push docker-registry.spekii.com/busybox

The push refers to a repository [docker-registry.spekii.com/busybox] (len: 1)
Sending image list
Pushing repository docker-registry.spekii.com/busybox (1 tags)
511136ea3c5a: Image successfully pushed 
6c991eb93460: Image successfully pushed 
9f4e93171ec5: Image successfully pushed 
2d8e5b282c81: Image successfully pushed 
Pushing tag for rev [2d8e5b282c81] on {https://docker-registry.spekii.com/v1/repositories/busybox/tags/latest}

*Be careful of using the same hostname when logging/tagging

Finally we can now add a start script. Few preparation…

useradd -r -s /bin/false docker-registry
chown docker-registry:docker-registry data

… and the script.

#!/bin/sh

export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin

BASE=$(basename $0)

# should be adapted in the default file
DOCKER_REGISTRY_PIDFILE=/var/run/$BASE.pid
DOCKER_REGISTRY_LOGFILE=/var/log/$BASE.log
DOCKER_REGISTRY_USER=docker-registry
DOCKER_REGISTRY_GROUP=docker-registry
DOCKER_REGISTRY_DIR=/opt/docker-registry

if [ -f /etc/default/$BASE ]; then
        . /etc/default/$BASE
fi

case "$1" in
        start)
                gunicorn -D --access-logfile $DOCKER_REGISTRY_LOGFILE -k gevent \
                --max-requests 100 --graceful-timeout 3600 \
                -t 3600 -b localhost:5000 -w 8 docker_registry.wsgi:application \
                -u $DOCKER_REGISTRY_USER -g $DOCKER_REGISTRY_GROUP \
                -p $DOCKER_REGISTRY_PIDFILE --chdir $DOCKER_REGISTRY_DIR
                ;;

        stop)
                PID=$(cat $DOCKER_REGISTRY_PIDFILE)
                kill $PID
                ;;

        restart)
                $0 stop
                $0 start
                ;;

        force-reload)
                $0 restart
                ;;
        *)
                echo "Usage: $0 {start|stop|restart}"
                exit 1
                ;;
esac

exit 0

1 comment :

  1. Thank you for the great post! This is going to save me a lot of time.

    One thing which i'm wondering, is it possible to add a caching layer to the apache2 configuration or would this be done in the Docker registry itself?

    ReplyDelete