Monday, July 15, 2019

Setting up private registry for docker images

The registry is a stateless and highly scalable server-side open source application permissive under Apache license, which let you store your images privately and makes internal distribution and management easy. In case you don't want private registry docker hub is the best place to store your images.

To configure own private registry follow below steps:


1. To start the registry container, which will be used as local registry on the docker host:

[root@localhost ~]# docker run -d -p 5000:5000 --restart=always --name registry -v /local_registry/images:/var/lib/registry registry:2
Unable to find image 'registry:2' locally
2: Pulling from library/registry
c87736221ed0: Pull complete
1cc8e0bb44df: Pull complete
54d33bcb37f5: Pull complete
e8afc091c171: Pull complete
b4541f6d3db6: Pull complete
Digest: sha256:77a8fb00c00b99568772a70f0863f6192ff2635e4af4e22e4d9c622edeb5f2de
Status: Downloaded newer image for registry:2
97f0845f8c3a0064ef0144aba57610e4c4f3d79947eed734d045f4d65b33a754


NOTE: In '-v /local_registry/images:/var/lib/registry' switch "/local_registry/images" is a folder on the host which will be used to store images and will be bind to "/var/lib/registry" container folder.


[root@localhost ~]# docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
97f0845f8c3a        registry:2          "/entrypoint.sh /etc…"   15 seconds ago      Up 13 seconds       0.0.0.0:5000->5000/tcp   registry


2. Pull any image from Docker public registry [Optional, as i don't have any other image for this demo]:

[root@localhost ~]# docker pull alpine
Using default tag: latest
latest: Pulling from library/alpine
e7c96db7181b: Pull complete
Digest: sha256:769fddc7cc2f0a1c35abb2f91432e8beecf83916c421420e6a6da9f8975464b6
Status: Downloaded newer image for alpine:latest


3. Tag image within local registry with new name:


[root@localhost ~]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
alpine              latest              055936d39205        13 days ago         5.53MB
nginx               latest              53f3fd8007f7        2 weeks ago         109MB
registry            2                   f32a97de94e1        2 months ago        25.8MB


[root@localhost ~]# docker tag alpine:latest localhost:5000/my-alpine-latest


[root@localhost ~]# docker image ls
REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
alpine                            latest              055936d39205        13 days ago         5.53MB
localhost:5000/my-alpine-latest   latest              055936d39205        13 days ago         5.53MB
nginx                             latest              53f3fd8007f7        2 weeks ago         109MB
registry                          2                   f32a97de94e1        2 months ago        25.8MB


4. Push newly tagged image to local registry:

[root@localhost ~]# docker push localhost:5000/my-alpine-latest
The push refers to repository [localhost:5000/my-alpine-latest]
f1b5933fe4b5: Pushed
latest: digest: sha256:bf1684a6e3676389ec861c602e97f27b03f14178e5bc3f70dce198f9f160cce9 size: 528


[root@localhost ~]# docker image ls
REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
alpine                            latest              055936d39205        13 days ago         5.53MB
localhost:5000/my-alpine-latest   latest              055936d39205        13 days ago         5.53MB
nginx                             latest              53f3fd8007f7        2 weeks ago         109MB
registry                          2                   f32a97de94e1        2 months ago        25.8MB


5. [OPTIONAL] you can delete images downloaded from Docker public registry and the tagged one.

[root@localhost ~]# docker image rm alpine:latest
Untagged: alpine:latest
Untagged: alpine@sha256:769fddc7cc2f0a1c35abb2f91432e8beecf83916c421420e6a6da9f8975464b6


[root@localhost ~]# docker image rm localhost:5000/my-alpine-latest
Untagged: localhost:5000/my-alpine-latest:latest
Untagged: localhost:5000/my-alpine-latest@sha256:bf1684a6e3676389ec861c602e97f27b03f14178e5bc3f70dce198f9f160cce9
Deleted: sha256:055936d3920576da37aa9bc460d70c5f212028bda1c08c0879aedf03d7a66ea1
Deleted: sha256:f1b5933fe4b5f49bbe8258745cf396afe07e625bdab3168e364daf7c956b6b81


6. To pull locally pushed image:

[root@localhost ~]# docker pull localhost:5000/my-alpine-latest
Using default tag: latest
latest: Pulling from my-alpine-latest
e7c96db7181b: Pull complete
Digest: sha256:bf1684a6e3676389ec861c602e97f27b03f14178e5bc3f70dce198f9f160cce9
Status: Downloaded newer image for localhost:5000/my-alpine-latest:latest


If you notice, this pushed image will get store to below path:

/local_registry/images/docker/registry/v2/repositories/my-alpine-latest

Unable to pull images from docker hub in your environment ?

A couple of days back I faced an issue where I was able to pull images from docker hub on my laptop when connecting from my home and same was failing when connecting in office. I tried setting a proxy on my RHEL OS with "export" env setting but still, it didn't work. Then after googling figured out the exact root cause.

Setting up proxy on OS environment (using export with RHEL) is not enough in case of docker, here you need to set proxy on one more level i.e. on docker settings. To do this follow the below steps:

Create a new file "http-proxy.conf" if not exists in the below folder with shown contents:

[root@localhost ~]# vi /etc/systemd/system/docker.service.d/http-proxy.conf

[Service]
Environment="HTTP_PROXY=http://proxy1.localnet.net:8080/"
Environment="HTTPS_PROXY=http://proxy1.localnet.net:8080/"

save and quit.


Restart docker service:
[root@localhost ~]# systemctl daemon-reload

[root@localhost ~]# systemctl restart docker


Verify if proxy is configured in docker settings:

[root@localhost ~]# docker info
.
.
.
HTTP Proxy: http://proxy1.localnet.net:8080/
HTTPS Proxy: http://proxy1.localnet.net:8080/
.
.
.

[root@localhost yum.repos.d]# systemctl show --property Environment docker
Environment=HTTP_PROXY=http://proxy1.localnet.net:8080/ HTTPS_PROXY=http://proxy1.localnet.net:8080/

Try pulling image from docker hub, not it should work fine.

Preparing RHEL 7.5 base image for docker container from scratch

Whenever we start working with a container, to start you need a base image for any specific Operating system as per your requirement. You can get base images for many OS distributions except RHEL OS as it needs licensing. So in case, you want to prepare a base image of RHEL operating system you can follow below steps which are pretty straight forward: 

Prerequisites:

Mount RHEL 7.5 ISO on /mnt and create a .repo file:

[root@localhost yum.repos.d]# cat /etc/yum.repos.d/local.repo
[localrepo]
name=Local Repository
baseurl=file:///mnt
gpgcheck=0
enabled=1


OPTIONAL: HTTP/HTTPS repository is needed when you need to install any packages inside a container, or while preparing containers.

[root@localhost yum.repos.d]# cat httplocal.repo
[rhel-core]
name=RHEL 7.5 Core
baseurl=http://web1.repo.local/linux/RedHat/7.5Server/en/os/x86_64/
gpgcheck=0
enabled=1

OPTIONAL: Set proxy if needed in your network.


Steps to create a base image:

[root@localhost ~]# export img_root=/rhel7-root

[root@localhost ~]# rpm --root ${img_root} --initdb

[root@localhost ~]# rpm --root ${img_root} -ivh /mnt/Packages/redhat-release-server-7.5-8.el7.x86_64.rpm
warning: /mnt/Packages/redhat-release-server-7.5-8.el7.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID fd431d51: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:redhat-release-server-7.5-8.el7  ################################# [100%]

[root@localhost ~]# rm -f ${img_root}/etc/yum.repos.d/*.repo

[root@localhost ~]# mkdir /rhel7-root/etc/yum.repos.d/

[root@localhost ~]# cp /etc/yum.repos.d/httplocal.repo ${img_root}/etc/yum.repos.d/httplocal.repo

[root@localhost ~]# rpm --root ${img_root} --import  /mnt/RPM-GPG-KEY-redhat-*

[root@localhost ~]# yum -y --installroot=${img_root} install yum

[root@localhost ~]# yum -y --installroot=${img_root} install net-tools iputils

Note: "net-tools and iputils" packages are optional, but in case if you won't install these packages, you will not be able to communicate to container as networking will be disabled. 

Once packages are installed check if chroot to the image location is working fine.

[root@localhost ~]# chroot ${img_root} /bin/bash
bash-4.2# ls

bash-4.2# exit
exit


[root@localhost ~]# rm -rf “${img_root}”/var/lib/rpm/__db*

[root@localhost ~]# rm -rf “${img_root}”/var/cache/yum

[root@localhost ~]# yum --installroot=${img_root} history sync

[root@localhost ~]# yum --installroot=${img_root} clean all


Create a tar file for a image filesystem and import it as an working base docker image:

[root@localhost ~]# tar -C ${img_root}/ -c . | docker import - rhel75base
sha256:4fe7ebbf140cabf573f7ce2c69a71f165c1a8d91d257d95e3ef073b9ca7f4213

Start a container and check if image is working fine and you are able to see virtual ethernet interface:

[root@localhost ~]# docker run -it rhel75base bash
bash-4.2# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.3  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:03  txqueuelen 0  (Ethernet)
        RX packets 6  bytes 508 (508.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


Note: Once in the container, you might need to set up proxy to reach httplocal.repo in case of further package installation.