Skip to content

Instantly share code, notes, and snippets.

@lotusirous
Last active May 31, 2018 09:48
Show Gist options
  • Save lotusirous/ddd1664405ebf4078250960ac320bdbe to your computer and use it in GitHub Desktop.
Save lotusirous/ddd1664405ebf4078250960ac320bdbe to your computer and use it in GitHub Desktop.
A guide to set up private docker registry in local machine

Set up docker private registry

A registry is an instance of the registry image, and runs within Docker. By default dockerd (docker daemon) pulls images from docker.hub, it requires an Internet connection to download images. In many cases, the server locates in a private network also have many advantages such as security policy, self-manage docker image, caching, etc. Docker provides docker registry and docker trusted registry with some differences for hosting a private registry server. This hands-on tutorial provides a briefly description for running a registry server. For more detail, please visit the official setup guide

This guide includes 2 steps:

  • Pull and configure a local registry server which comes from github repo
  • Configure docker client to fetch images from private server.

Overview

We're gonna set up a registry server runs on http://localhost:5000 and stored images at /var/lib/registry. Once server is up, we pull a python image from docker.hub, then push to our local private server.

TL;DR

Use the following steps for running docker registry server in production.

dockerd fetchs images with a secure protocol HTTPS by default. Thus, the registry server should date with https with various options

You have to install cfssl to your path:

sudo curl -s -L -o /bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
sudo curl -s -L -o /bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
sudo chmod +x /bin/{cfssl,cfssljson}

The following configuration is from core-os

mkdir $HOME/cert
mkdir $HOME/registry
cd $HOME/cert
echo '{"CN":"CA","key":{"algo":"rsa","size":2048}}' | cfssl gencert -initca - | cfssljson -bare ca -
echo '{"signing":{"default":{"expiry":"43800h","usages":["signing","key encipherment","server auth","client auth"]}}}' > ca-config.json
export ADDRESS=192.168.233.161,192.168.233.160,192.168.233.162 # This IP list is the white list for our cluster.
export NAME=server
echo '{"CN":"'$NAME'","hosts":[""],"key":{"algo":"rsa","size":2048}}' | cfssl gencert -config=ca-config.json -ca=ca.pem -ca-key=ca-key.pem -hostname="$ADDRESS" - | cfssljson -bare $NAME
export ADDRESS=
export NAME=client
echo '{"CN":"'$NAME'","hosts":[""],"key":{"algo":"rsa","size":2048}}' | cfssl gencert -config=ca-config.json -ca=ca.pem -ca-key=ca-key.pem -hostname="$ADDRESS" - | cfssljson -bare $NAME

After this step, you have the following files in current directory:

$ ls $HOME/cert/
               ca-config.json
               ca.csr
               ca-key.pem
               ca.pem
               client.csr
               client-key.pem
               client.pem
               server.csr
               server-key.pem
               server.pem

Start server in debug mode.

docker run -p 5443:5443 --restart=always \
--name registry \
-e REGISTRY_HTTP_SECRET=5iT35m_1nf1n1g4u \
-e REGISTRY_HTTP_ADDR=0.0.0.0:5443 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/cert/server.pem \
-e REGISTRY_HTTP_TLS_KEY=/cert/server-key.pem \
-v $HOME/cert:/cert \
-v $HOME/registry:/var/lib/registry  \
registry:2

We reconfigure docker daemon using the /etc/docker/daemon.json file for all servers.

  1. Create or modify /etc/docker/daemon.json
{ "insecure-registries":["192.168.233.160:5443"] }

Copy the client key to other docker machine.

/etc/docker/certs.d/
- 192.168.233.160/ # registry server ip without port
  - ca.csr
  - ca-key.pem
  - ca.pem
  - client.csr
  - client-key.pem
  - client.pe
  1. Restart docker daemon for all servers.
sudo systemctl restart docker

Inspect registry server from scratch

The following steps are my approaches to configure registry server. It uses registry

$ docker run -d -p 5000:5000 --restart=always --name registry registry:2
  • -d daemon mode
  • -p 5000:5000 mapping port physical → container
  • --restart=always run this container after docker started
  • --name registry container name

Now, the service is running a service at port 5000

$ docker ps

Verify:

$ docker images -a
REPOSITORY    TAG     IMAGE ID       CREATED         SIZE
registry      2       d1fd7d86a825   4 months ago    33.3MB

In order to copy an image to local repo, we perform the following steps:

  1. Pull image from docker.hub
  2. Assign tag for images
  3. Push to local registry
$ docker pull python:alpine3.6 # pull image from docker.hub
$ docker tag python:alpine3.6 localhost:5000/python:alpine3.6 # assign tag for image
$ docker push localhost:5000/python:alpine3.6 # push to local repo

Verify uploaded image in registry

http GET localhost:5000/v2/_catalog
{
    "repositories": [
        "python"
    ]
}

Change stored directory

Once the server is up and run. we inspect the server default location.

$ docker inspect registry
...
"Mounts":[
      {
         "Type":"volume",
         "Name":"e71f65b9da143a99e8f391b3f5ab8903184cae58a2d3416de23a8d375775e822",
         "Source":"/var/lib/docker/volumes/e71f65b9da143a99e8f391b3f5ab8903184cae58a2d3416de23a8d375775e822/_data",
         "Destination":"/var/lib/registry",
         "Driver":"local",
         "Mode":"",
         "RW":true,
         "Propagation":""
      }
   ]

...

Now, we can change the location by docker volume feature.

docker run -d \
  -p 5000:5000 \
  --restart=always \
  --name registry \
  -v /mnt/registry:/var/lib/registry \
  registry:2
  • -v map physical path /mnt/registry → container path /var/lib/registry

Backup and restore registry volume

Simple solution:

  • Back up by compressing physical directory.
$ tar cvf registry.tar.gz /mnt/registry
  • Restore by extracting the compressed file, then run again with mapping volume.

Options

Remove local cache

$ docker image remove python:alpine3.6
$ docker image remove localhost:5000/python:alpine3.6

Stop container

docker container stop <container_name>

Change service inside container port by specify environment variable REGISTRY_HTTP_ADDR with -e flag

docker run -d \
  -e REGISTRY_HTTP_ADDR=0.0.0.0:5001 \
  -p 5001:5001 \
  --name registry-test \
  registry:2

Configure container with volume.

$ docker volume create registry
$ docker-private-registry docker volume inspect registry
[
  {
    "CreatedAt": "2018-05-28T00:45:06+09:00",
    "Driver": "local",
    "Labels": {},
    "Mountpoint": "/var/lib/docker/volumes/registry/_data",
    "Name": "registry",
    "Options": {},
    "Scope": "local"
  }
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment