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
Thank you for the great post! This is going to save me a lot of time.
ReplyDeleteOne 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?