setting up private docker registry: docker registry v2 and image upoad to docker registry v2

As title of this post states in text below we are going to describe process how to set up private docker registry and how to create custom docker image and then upload it to our newly created docker registry. We are going to use v2 Registry server for Docker.

You know what is docker… don’t you? If not then take some days of and start reading docker documentation you can find at docker web docker documentation

When it comes to docker registry, one can use docker hub registry, or some other provided by Linux vendor … If you do not want to use docker hub, and you use Linux version which is not officially vendor supported ( for example Fedora ), then you can create your own docker registry and push images there and thus have more control over it. Other reason for own/private docker registry can be that you have private / classified docker images ( eg, bank application running in container and processing client information ) which you want to keep “in house” without exposing them to third party locations.

v2 Docker registry main advantage over docker registry v1 is better API feature set and it is worth to invest time to learn how to deploy it. This post is short to write now about all docker registry v2 APIs and I recommend to read about API features Docker Registry HTTP API V2

In order use local docker registry, we have to install and configure it and afterwards be able to push images to it.
In process below we will describe docker registry process setup, and I am going to use Fedora rawhide as operating system,in your tests, you can use other Linux distribution than Fedora, but ensure it has docker-distribution package, or some name variation of it.
dnf info docker-distribution gives below info

# rpm -qi docker-distribution 
Name        : docker-distribution
Version     : 2.1.1
Release     : 4.fc24
Architecture: x86_64
Install Date: Fri 27 Nov 2015 11:20:18 AM CET
Group       : Unspecified
Size        : 11721281
License     : ASL 2.0
Signature   : RSA/SHA256, Wed 28 Oct 2015 03:18:18 PM CET, Key ID 73bde98381b46521
Source RPM  : docker-distribution-2.1.1-4.fc24.src.rpm
Build Date  : Wed 28 Oct 2015 03:01:16 PM CET
Build Host  :
Relocations : (not relocatable)
Packager    : Fedora Project
Vendor      : Fedora Project
URL         :
Summary     : Docker toolset to pack, ship, store, and deliver content
Description :
Docker toolset to pack, ship, store, and deliver content

Ok, let’s proceed and install docker-distribution package
dnf instal docker-distribution
After installation of some packages, I almost always run rpm -ql which will list me files delivered by particular package, and then I filter only /etc/ and systemd related files, in this case

 # rpm -ql docker-distribution | egrep 'etc|systemd'

At this stage, of main interest is /usr/lib/systemd/system/docker-distribution.service from where we see it will use

ExecStart=/usr/bin/registry /etc/docker-distribution/registry/config.yml

to start service

Docker has comprehensive documentation regarding parameters supported in config.yml, you can find it at Registry Configuration Reference and I recommend to check it in order to better understand what all is possible to configure.

In my /etc/docker-distribution/registry/config.yml I have below

version: 0.1
    service: registry
        layerinfo: inmemory
        rootdirectory: /var/lib/registry
    net: tcp 
    host: https://e-makina.elvirhome.local:5000
    secret: elkosecret
            certificate: /etc/certs/elvirhome.local.crt
            key: /etc/certs/elvirhome.local.key
                realm: elvirhome.local
                path: /etc/certs/dockerpasswd

I decided to to use htpasswd authentication – good enough for my test case, for all other supported authentication methods check docker documentation docker distribution auth options
I also generated self signed TLS certificate. Note that config.yml must be valid yml file and follow yml file formatting,so pay attention on it

# mkdir -p /etc/certs; cd /etc/certs; openssl req -newkey rsa:4096 -nodes -sha256 -keyout elvirhome.local.key -x509 -days 365 -out elvirhome.local.crt

and created hpasswd file

 cd /etc/certs; htpasswd  -c -B dockerpasswd elvir

Now, we are ready to start docker-distribution service

# systemctl restart docker.service 
# systemctl start docker-distribution.service

and check does it run as expected

# systemctl status docker-distribution.service 
● docker-distribution.service - v2 Registry server for Docker
   Loaded: loaded (/usr/lib/systemd/system/docker-distributio
   Active: active (running) since Thu 2015-12-24 17:12:47 CET
 Main PID: 26760 (registry)
    Tasks: 9 (limit: 512)
   CGroup: /system.slice/docker-distribution.service
           └─26760 /usr/bin/registry /etc/docker-distribution

If docker-registry, try to login to docker registry

 $ docker login e-makina.elvirhome.local:5000
Username: elvir
WARNING: login credentials saved in /home/elvir/.docker/config.json
Login Succeeded

It works, we can authenticate against local/private docker registry. In /home/$user/.docker/config.json you can find authentication parameters saved – they will be used next time, so and no need to enter password again. Above is more / less all what is necessary in order to push docker image to your own private docker registry.

However, I would like to draw attention to storage options. Docker registry v2 supports azure,gcs,s3,swift, rados and local storage which I use above – due to its cost and accessibility – free on my machine. Check full list of supported storage options and their configuration parameters docker distribution storage options
If instead local file system some other storage backend is planned to use, then above configuration will slightly differ. I still cannot say how docker operations as push/pull will perform depending if images are pushed/pulled from cloud ( non local ) storage. In this case when docker registry uses cloud based storage, new player comes in game – network latency / performance. If you consider this option, then do some tests in advance.

Now, let’s build our own image and push it to repository. Below will build image based on Fedora rawhide, with name mynewimage, later it will be tagged and pushed to local registry

$ git clone
$ cd docker/contrib
$ sh mynewimage 
$ $ docker images | grep mynewimage 
REPOSITORY                                 TAG                 IMAGE ID            CREATED             SIZE
mynewimage                                 mynewimage          68dbdc9770ec        7 seconds ago       180.1 kB
$ docker tag 68dbdc9770ec e-makina.elvirhome.local:5000/mynewimage 
$ docker push e-makina.elvirhome.local:5000/mynewimage

If you access registry via web pointing it to location you specified for host: in config.yml ( you have to use username / password specified in htpasswd step ) there will be list of images which are already pushed in repository, and here starts API heaven. Happy docker registry and docker API hacking!


#docker, #docker-registry, #docker-registry-v2-api, #docker-distribution, #linux


If you install docker-1.7 ( or later ) then you will get with it docker-storage-script delivered

# rpm -q docker
#rpm -ql docker | grep storage

/usr/bin/docker-storage-setup is responsible for docker storage configuration, it is shell script and if you open and read it, you can get all what it does from there.

docker-storage-setup will follow instructions in /usr/lib/docker-storage-setup/docker-storage-setup and configure docker storage backend based on parameters there. In most cases you are fine with defaults, but you can change them if you want.

In case you decide to step away from default values ( eg, to give volume group name you like, or to specify block devices you want to use… ) then it is possible too. All you need to do is to

cp /usr/lib/docker-storage-setup/docker-storage-setup /etc/sysconfig

Edit, /etc/sysconfig/docker-storage-setup

and start docker

systemctl start docker

In docker-storage-setup, interesting values are

DEVS – list of block devices to be used for docker storage
VG – volume group name
CHUNK_SIZE – default is 512K

Pay attention on CHUNK_SIZE – value of 512K is showed as most efficient from storage backend performance point of view. Check Determine the default optimal chunk/block size for docker workload and Adjust default chunksize on thinp volume created by docker-storage-setup

#docker, #docker-performance, #docker-storage-setup, #linux, #thin-lvm

build kubernetes binaries

If you due to some reason want to get and test latest and bleeding edge kubernetes binaries, one of ways to do that is described below

# yum install -y golang glibc-static device-mapper-devel btrfs-progs btrfs-progs-devel sqlite-devel docker

  1. systemctl start docker
  2. systemctl enable docker
  3. git clone
  4. cd kubernetes/build/


this process will take some time as it is going to download necessary golang images necessary for build – image download will be run only once, every next build will (re)use these already downloaded images ( or it will get only “delta” changes between image already present on system and its update)

Once build is finished, binaries will be in ~/kubernetes/_output/dockerized/bin/linux/amd64
Small script doing this is


enter into running docker container

sometimes it is handy to enter into running docker container and to check some stuff while docker container is running. docker has handy tools to do that

we need first get PID of docker container we want to enter in

#docker inspect --format {{.State.Pid}} $(docker ps | grep | awk '{print $1 }')
replace in above command with name of your container

Once you have PID using nsenter you can enter into container

#nsenter -m -u -n -i -p -t $PID

meaning of particular nsenter parameters is listed below

# nsenter -h
nsenter [options] [args...]
-t, --target target process to get namespaces from
-m, --mount [=] enter mount namespace
-u, --uts [=] enter UTS namespace (hostname etc)
-i, --ipc [=] enter System V IPC namespace
-n, --net [=] enter network namespace
-p, --pid [=] enter pid namespace
-r, --root [=] set the root directory
-w, --wd [=] set the working directory
-F, --no-fork do not fork before exec'ing
-h, --help display this help and exit
-V, --version output version information and exit
For more details see nsenter(1)

please note that nsenter is shipped as part ( at least on RHEL based distros ) on util-linux package

#rpm -qf $(which nsenter)

#containers-nsenter, #docker-inspect

what if you do not want to run docker pull?

In Red Hat Security blog post before you initiate docker pull is explained why running docker pull ( at current state of docker ) cannot be ultimately considered as wise step.

Unfortunately, all instructions out there related to starting with docker points exclusively to docker pull as way to go – not giving much room discussion from above blog post.

If you are security aware ( some would say paranoid ), then you have couple options to deal with this

1. divide pull and load steps – this means get .tar.gz archive of docker image and then load docker image after downloading it, this means you can get docker image using wget ( eg fedora Fedora docker images in .tar.gz format ) and then load it with docker load With this these you achieve same result but before loading image you can check md5 sum of image you want to load and ensure it is really one you want.
I provided link to Fedora .tar.gz docker image format.Asking your favorite search ( evil ) machine will guide you to other images – Centos/Debian.

I recommend you to read below articles in order to understand a bit more about how docker handle stuff in background

a. docker insecurity blog post
b. Cryptographic Signing of Core Images

2. With 1. implemented, there is no need any more to get images from internet – as long as there is not ( and you want to use it ) updated base image ( in above case Fedora image ). From this point you can use docker for your purposes, and if you want to build new image you can use docker build --tag=mynewimage Dockerfile where in Dockerfile you specify that you want to build new image from one you already have. Beware here that,if docker build is not able to find image to build from – it will search against – so read above article in to figure out how to prevent this.
Docker team wrote excellent document on writing dockerfiles and I recommend to read it in advance to get better insight on Dockerfile structure.

3. You can use docker-registry and build you local docker registry from where you can pull images – without internet interaction. In order to download images from docker registry you will first need to preload / upload ones you want there.

In my future blog posts, I will write detailed howto how to create base image(s), how to configure and start your local docker registry service and how to upload images to there