Docker Private Registry

Docker depends on registry component, which is a repository where docker images are stored, and available to be pulled/pushed by docker instances. Although Docker (https://www.docker.io/) sells "ready to use" private registries, you may want to avoid exposing your docker containers outside of your private IT infrastructure (risk of internal binaries/scripts/ip leak, security team requirement, bandwidth too limited, ...) This tutorial will show up how you can install and run your own Docker registry.

Pre-requisites

  • OpenSVC service managing docker containers (As described in the parent topic)
  • Official Docker Registry image

Service Creation

Preparing OpenSVC registry service:

root@deb1:/etc/opensvc# mkdir registry.opensvc.com.dir
root@deb1:/etc/opensvc# ln -s registry.opensvc.com.dir registry.opensvc.com.d
root@deb1:/etc/opensvc# ln -s ../bin/svcmgr registry.opensvc.com
root@deb1:/etc/opensvc# getent hosts registry.opensvc.com
37.59.71.25     registry.opensvc.com

Completing with service configuration file (copy/paste ready):

cat > /etc/opensvc/registry.opensvc.com.env << EOF
[DEFAULT]
autostart_node = deb1.opensvc.com
app = OSVCLAB
service_type = DEV
nodes = deb1.opensvc.com
docker_data_dir = /opt/registry.opensvc.com/dockerdata
docker_daemon_args = --ip 37.59.71.25

[container#1]
type = docker
run_image = unknown_at_the_moment

[ip#1]
ipdev = eth0
ipname = registry.opensvc.com

[vg#1]
vgname = vgregistry

[fs#1]
mnt_opt = rw
mnt = /opt/registry.opensvc.com
dev = /dev/mapper/vgregistry-lvregistryroot
type = ext4

[fs#2]
mnt_opt = rw
mnt = /opt/registry.opensvc.com/dockerdata
dev = /dev/mapper/vgregistry-lvdockerdata
type = ext4

[fs#3]
mnt_opt = rw
mnt = /opt/registry.opensvc.com/registrydata
dev = /dev/mapper/vgregistry-lvregistrydata
type = ext4
EOF

Storage configuration consists in 3 logical volumes hosted in a volume group dedicated to OpenSVC registry service :

  • [fs#1] is the root filesystem for OpenSVC registry service
  • [fs#2] is the docker dedicated filesystem, where images are stored, and layering is managed
  • [fs#3] is the registry dedicated filesystem, which will be presented into the registry container, so as to store all private docker images.

Note

As a general recommendation (not only when implementing a private docker registry), it is highly recommended to use a data volume presented into the container to store all your datas. This way you will be able to delete/recreate your container without data loss. With another dedicated block device, it is also a convenient way if you need to use block device replication, either locally (EMC Snap/Clones, IBM FlashCopy, etc), or remotely (EMC SRDF/RecoverPoint, IBM PPRC, etc).

Check if OpenSVC service is ready:

root@deb1:/etc/opensvc# registry.opensvc.com print status
send /etc/opensvc/registry.opensvc.com.env to collector ... OK
update /var/lib/opensvc/registry.opensvc.com.push timestamp ... OK
registry.opensvc.com
overall                   warn
|- avail                  warn
|  |- container#1    .... down     unknown_at_the_moment
|  |  |                            # docker daemon is not running
|  |- vg#1           .... down     vgregistry
|  |- fs#1           .... down     /dev/mapper/vgregistry-lvregistryroot@/opt/registry.opensvc.com
|  |- fs#2           .... down     /dev/mapper/vgregistry-lvdockerdata@/opt/registry.opensvc.com/dockerdata
|  |- fs#3           .... down     /dev/mapper/vgregistry-lvregistrydata@/opt/registry.opensvc.com/registrydata
|  '- ip#1           .... down     registry.opensvc.com@eth0
|- sync                   n/a
'- hb                     n/a

Docker Image Pull

We will use the official registry image (https://index.docker.io/_/registry/)

Start minimal resource to populate docker local data

root@deb1:/etc/opensvc# registry.opensvc.com startip
16:50:28 INFO    REGISTRY.OPENSVC.COM.IP#1    checking 37.59.71.25 availability
16:50:32 INFO    REGISTRY.OPENSVC.COM.IP#1    ifconfig eth0:1 37.59.71.25 netmask 255.255.255.224 up
16:50:32 INFO    REGISTRY.OPENSVC.COM.IP#1    arping -U -c 1 -I eth0 -s 37.59.71.25 37.59.71.25
root@deb1:/etc/opensvc# registry.opensvc.com startfs
16:50:36 INFO    REGISTRY.OPENSVC.COM.VG#1    vgchange --addtag @deb1.opensvc.com vgregistry
16:50:37 INFO    REGISTRY.OPENSVC.COM.VG#1    output:
  Volume group "vgregistry" successfully changed

16:50:37 INFO    REGISTRY.OPENSVC.COM.VG#1    vgchange -a y vgregistry
16:50:37 INFO    REGISTRY.OPENSVC.COM.VG#1    output:
  3 logical volume(s) in volume group "vgregistry" now active

16:50:37 INFO    REGISTRY.OPENSVC.COM.FS#1    e2fsck -p /dev/mapper/vgregistry-lvregistryroot
16:50:37 INFO    REGISTRY.OPENSVC.COM.FS#1    output:
/dev/mapper/vgregistry-lvregistryroot: clean, 11/32768 files, 6257/131072 blocks

16:50:37 INFO    REGISTRY.OPENSVC.COM.FS#1    mount -t ext4 -o rw /dev/mapper/vgregistry-lvregistryroot /opt/registry.opensvc.com
16:50:37 INFO    REGISTRY.OPENSVC.COM.FS#2    create missing mountpoint /opt/registry.opensvc.com/dockerdata
16:50:37 INFO    REGISTRY.OPENSVC.COM.FS#2    e2fsck -p /dev/mapper/vgregistry-lvdockerdata
16:50:37 INFO    REGISTRY.OPENSVC.COM.FS#2    output:
/dev/mapper/vgregistry-lvdockerdata: clean, 11/131072 files, 25388/524288 blocks

16:50:37 INFO    REGISTRY.OPENSVC.COM.FS#2    mount -t ext4 /dev/mapper/vgregistry-lvdockerdata /opt/registry.opensvc.com/dockerdata
16:50:37 INFO    REGISTRY.OPENSVC.COM.FS#3    create missing mountpoint /opt/registry.opensvc.com/registrydata
16:50:37 INFO    REGISTRY.OPENSVC.COM.FS#3    e2fsck -p /dev/mapper/vgregistry-lvregistrydata
16:50:37 INFO    REGISTRY.OPENSVC.COM.FS#3    output:
/dev/mapper/vgregistry-lvregistrydata: clean, 11/131072 files, 25388/524288 blocks

16:50:37 INFO    REGISTRY.OPENSVC.COM.FS#3    mount -t ext4 /dev/mapper/vgregistry-lvregistrydata /opt/registry.opensvc.com/registrydata

root@deb1:/etc/opensvc# registry.opensvc.com print status
registry.opensvc.com
overall                   warn
|- avail                  warn
|  |- container#1    .... down     unknown_at_the_moment
|  |  |                            # docker daemon is not running
|  |- vg#1           .... up       vgregistry
|  |- fs#1           .... up       /dev/mapper/vgregistry-lvregistryroot@/opt/registry.opensvc.com
|  |- fs#2           .... up       /dev/mapper/vgregistry-lvdockerdata@/opt/registry.opensvc.com/dockerdata
|  |- fs#3           .... up       /dev/mapper/vgregistry-lvregistrydata@/opt/registry.opensvc.com/registrydata
|  '- ip#1           .... up       registry.opensvc.com@eth0
|- sync                   n/a
'- hb                     n/a
root@deb1:/etc/opensvc# registry.opensvc.com docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

Pull docker image

root@deb1:/etc/opensvc# registry.opensvc.com docker pull registry:latest
Pulling repository registry
5670839b64ba: Download complete
511136ea3c5a: Download complete
/* removing download logs */

root@deb1:/etc/opensvc# registry.opensvc.com docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
registry            latest              5670839b64ba        3 days ago          554 MB

Docker Registry Setup

We have to configure our OpenSVC container object so as to run our private registry. Let's modify file /etc/opensvc/registry.opensvc.com.env like below :

Config Section:

[container#1]
type = docker
run_image = 5670839b64ba
run_args = -v /opt/registry.opensvc.com/registrydata:/registrydata -e STORAGE_PATH=/registrydata -p 5000:5000
  • -v /opt/registry.opensvc.com/registrydata:/registrydata is a volume mapping. We want to present our dedicated registry data volume into the container, mounted on /registrydata.
  • -e STORAGE_PATH=/registrydata : requiring Docker Registry to use folder /registrydata to store persistent data.
  • -p 5000:5000 expose network port 5000

Warning

take care of this bug https://github.com/dotcloud/docker-registry/issues/401 when modifying STORAGE_PATH

Docker Registry Start

After modifying the service configuration file

root@deb1:/etc/opensvc# registry.opensvc.com print status
send /etc/opensvc/registry.opensvc.com.env to collector ... OK
update /var/lib/opensvc/registry.opensvc.com.push timestamp ... OK
registry.opensvc.com
overall                   warn
|- avail                  warn
|  |- container#1    .... down     registry:latest
|  |  |                            # can not find container id
|  |- vg#1           .... up       vgregistry
|  |- fs#1           .... up       /dev/mapper/vgregistry-lvregistryroot@/opt/registry.opensvc.com
|  |- fs#2           .... up       /dev/mapper/vgregistry-lvdockerdata@/opt/registry.opensvc.com/dockerdata
|  |- fs#3           .... up       /dev/mapper/vgregistry-lvregistrydata@/opt/registry.opensvc.com/registrydata
|  '- ip#1           .... up       registry.opensvc.com@eth0
|- sync                   n/a
'- hb                     n/a

Registry start

root@deb1:/etc/opensvc# registry.opensvc.com startcontainer
17:03:12 INFO    REGISTRY.OPENSVC.COM.CONTAINER#1 docker -H unix:///var/lib/opensvc/registry.opensvc.com/docker.sock run -t -i -d --name=registry.opensvc.com.container.1 -v /opt/registry.opensvc.com/registrydata:/registrydata -e STORAGE_PATH=/registrydata -p 5000:5000 5670839b64ba
17:03:12 INFO    REGISTRY.OPENSVC.COM.CONTAINER#1 output:
1c235fe957467097da19635f793ecf100d99100753ebdfe5d430142a70bfac73

17:03:12 INFO    REGISTRY.OPENSVC.COM.CONTAINER#1 wait for container up status
17:03:12 INFO    REGISTRY.OPENSVC.COM.CONTAINER#1 wait for container operational

root@deb1:/etc/opensvc# registry.opensvc.com print status
registry.opensvc.com
overall                   up
|- avail                  up
|  |- container#1    .... up       1c235fe95746@registry:latest
|  |- vg#1           .... up       vgregistry
|  |- fs#1           .... up       /dev/mapper/vgregistry-lvregistryroot@/opt/registry.opensvc.com
|  |- fs#2           .... up       /dev/mapper/vgregistry-lvdockerdata@/opt/registry.opensvc.com/dockerdata
|  |- fs#3           .... up       /dev/mapper/vgregistry-lvregistrydata@/opt/registry.opensvc.com/registrydata
|  '- ip#1           .... up       registry.opensvc.com@eth0
|- sync                   n/a
'- hb                     n/a

root@deb1:/etc/opensvc# registry.opensvc.com docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                        NAMES
1c235fe95746        registry:latest     /bin/sh -c 'exec doc   21 seconds ago      Up 21 seconds       37.59.71.25:5000->5000/tcp   registry.opensvc.com.container.1

Our registry is up & running.

Warning

The docker registry does not deal with access control. As soon as the docker container is up, everyone is allowed to push/pull images to/from the registry. You have to complete the solution with either ip filtering, or authentification solution. You can also workaround by binding registry to loopback ip address like 127.0.0.1, and create local accounts, so as users are able to open a ssh tunnel to the registry tcp port.

Testing the registry

The environment used to test the registry is a mac laptop, running boot2docker.

Macbook local docker repository is empty

17:05:35 averon@macbookpro:[~] # docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

Populating Macbook docker repository with a Docker image, from public Docker registry

17:05:37 averon@macbookpro:[~] # docker pull busybox:latest
Pulling repository busybox
98b9fdab1cb6: Download complete
511136ea3c5a: Download complete
b6c0d171b362: Download complete
9798716626f6: Download complete

17:06:41 averon@macbookpro:[~] # docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
busybox             latest              98b9fdab1cb6        3 days ago          2.433 MB

Tagging image to be able to push it to the private registry

17:07:25 averon@macbookpro:[~] # docker tag 98b9fdab1cb6 registry.opensvc.com:5000/busybox:private

17:07:54 averon@macbookpro:[~] # docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
busybox                             latest              98b9fdab1cb6        3 days ago          2.433 MB
registry.opensvc.com:5000/busybox   private             98b9fdab1cb6        3 days ago          2.433 MB

Pushing image to the private registry

17:09:16 averon@macbookpro:[~] # docker push registry.opensvc.com:5000/busybox:private
The push refers to a repository [registry.opensvc.com:5000/busybox] (len: 1)
Sending image list
Pushing repository registry.opensvc.com:5000/busybox (1 tags)
511136ea3c5a: Image successfully pushed
b6c0d171b362: Image successfully pushed
9798716626f6: Image successfully pushed
98b9fdab1cb6: Image successfully pushed
Pushing tag for rev [98b9fdab1cb6] on {http://registry.opensvc.com:5000/v1/repositories/busybox/tags/private}

Instantiating container and modifying it

12:01:21 averon@macbookpro:[~] # docker run -t -i registry.opensvc.com:5000/busybox:private
/ # touch /my_new_datafile
/ # cat > /my_new_datafile
docker container
/ #                     ### issuing keys ctrl+d to exit container
12:04:00 averon@macbookpro:[~] #

Committing changes to make new image from container

12:06:33 averon@macbookpro:[~] # docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
12:06:35 averon@macbookpro:[~] # docker commit --message="Added datafile to container" --author="Arnaud Veron <arnaud.veron@opensvc.com>" 51104d236675 registry.opensvc.com:5000/busybox:datafile
c56eb09567b98e3fd67c1c94a4cb65a552dc7447843f5415d1553ded3bd22a88
12:07:12 averon@macbookpro:[~] #

Pushing new image to the private registry

12:08:05 averon@macbookpro:[~] # docker push registry.opensvc.com:5000/busybox:datafile
The push refers to a repository [registry.opensvc.com:5000/busybox] (len: 1)
Sending image list
Pushing repository registry.opensvc.com:5000/busybox (1 tags)
Image 511136ea3c5a already pushed, skipping
Image b6c0d171b362 already pushed, skipping
Image 9798716626f6 already pushed, skipping
Image 98b9fdab1cb6 already pushed, skipping
c56eb09567b9: Image successfully pushed
Pushing tag for rev [c56eb09567b9] on {http://registry.opensvc.com:5000/v1/repositories/busybox/tags/datafile}

It works !