How to Setup Docker Private Registry on CentOS 7.x / RHEL 7.x

Whenever we install Docker on CentOS or RHEL Servers Docker public Registry is enabled so when we run ‘docker pull‘ or ‘docker search‘ command it will go to Docker public registry (Docker Hub) and will fetch the required container images. But it is not idea to fetch the Docker container images from public registry when you are using Docker in an organization, for the best practice we should have our own private Docker registry or repository. Docker Registry or repository is a place where Docker container images are stored.

In this article I will demonstrate how to setup our own Docker private registry on CentOS 7.x / RHEL 7.x.  I will be using three CentOS 7.x Servers and assuming docker is already installed and its service is up and running on all three servers. Below are the details of my three servers:

  • docker-repo.example.com { 192.168.0.60} -> It will act as my Docker private Registry Server
  • dkengine1.example.com { 192.168.0.70} -> On this Server Docker admins and developers will create their own container images either with dockerfile or with compose and then they will upload these images to their own docker private registry server (docker-repo.example.com) with docker push command
  • dkengine2.example.com { 192.168.0.80} -> On this Server we will download docker container  images from our own private registry server with ‘docker pull‘ command

Note : Update the /etc/hosts file in case DNS server is not configured so that servers can be reachable with their respective hostname or dns name.

192.168.0.60     docker-repo.example.com docker-repo
192.168.0.70     dkengine1.example.com  dkengine1
192.168.0.80     dkengine2.example.com dkengine2

Docker-Private-Registry-Setup

Perform the following steps to setup our own Docker Private Registry as per above discussed scenario

Step:1 Download and start registry Container on your private registry server

Login to the server which you want to configure as Docker Private Registry Server, in my case it is “docker-repo.example.com” . I am assuming Docker package is already installed on it and its service is up and running. In case Docker is not installed please refer the below

Next task is to start the program or script which will configure and make your server as Registry Server. That Program or script  is started by running a docker registry container. Let’s first download the registry container using beneath command

[root@docker-repo ~]# docker pull registry

Once the image is downloaded verify which commands will be executed when we start registry container image.

[root@docker-repo ~]# docker history registry

Docker-history-registry-command

Now start the registry container using below command

[root@docker-repo ~]# docker run -dit -p 5000:5000 --name registry registry
bf8e703b0149211bb923beeb042f8e656bf407b21646f101eb58e0acd4409c24
[root@docker-repo ~]#

Above Command will start the registry container with name registry and also we set the patting rule so that if any request comes to ‘docker-repo.example.com‘ on 5000 port then request will be redirected to registry container on 5000 port.

[root@docker-repo ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
bf8e703b0149        registry            "/entrypoint.sh /e..."   5 minutes ago       Up 5 minutes        0.0.0.0:5000->5000/tcp   registry
[root@docker-repo ~]#

Note: In case firewall is enabled on your private registry server then open 80 port using the following command

[root@docker-repo ~]# firewall-cmd --permanent --add-port=80/tcp
success
[root@docker-repo ~]# firewall-cmd --reload
success
[root@docker-repo ~]#

Step:2 Create Docker Container Image and upload it to Private  Registry Server  

Let’s assume I have build Ubuntu 16.04 docker container image with Dockerfile on ‘dkengine1.example.com‘. In Case you are not familiar with dockerfile then refer the below :

We can upload a container image to the  registry server with “docker push” command but before start uploading it we have make two changes

1 Make sure the image name is created with format  “servername:portnumber/imagename:tags“. By default docker pull command will try to upload the image in public registry and if we create image name with format mentioned above then  docker pull command will upload it to the server  mentioned in the image name. so in my case server name would be “docker-repo.example.com”

To change the name of docker image use docker tag command, example is shown below

[root@dkengine1 ~]# docker tag ubuntu:16.04 docker-repo.example.com:5000/ubuntu:16.04 
[root@dkengine1 ~]#

2 Change the docker push https connection to http. Whenever we use ‘docker push’ command it will try to make https connection to the registry server but in case of private registry server setup, it accepts only http connection from the client(dkengine1.example.com)

Edit the file “/usr/lib/systemd/system/docker.service” and change the parameter

ExecStart=/usr/bin/dockerd

to

ExecStart=/usr/bin/dockerd –insecure-registry docker-repo.example.com:5000

docker-service-file

Reload daemon service and restart Docker service

[root@dkengine1 ~]# systemctl daemon-reload
[root@dkengine1 ~]# systemctl restart docker
[root@dkengine1 ~]#

Now upload the image to private registry server using beneath command

[root@dkengine1 ~]# docker push docker-repo.example.com:5000/ubuntu:16.04
The push refers to a repository [docker-repo.example.com:5000/ubuntu]
56827159aa8b: Pushed
440e02c3dcde: Pushed
29660d0e5bb2: Pushed
85782553e37a: Pushed
745f5be9952c: Pushed
16.04: digest: sha256:6b079ae764a6affcb632231349d4a5e1b084bece8c46883c099863ee2aeb5cf8 size: 1357
[root@dkengine1 ~]#

Step:3 Download Docker Container image from Private Registry Server

Login  to ‘dkengine2.example.com’ server and use ‘docker pull’ command to download container image from your private registry server. By default docker pull command also makes https connection with registry server but our private registry accepts only http connection.

Edit the file “/usr/lib/systemd/system/docker.service” and change the parameter

ExecStart=/usr/bin/dockerd

to

ExecStart=/usr/bin/dockerd –insecure-registry docker-repo.example.com:5000

Reload daemon service and restart docker service

[root@dkengine2 ~]# systemctl daemon-reload ; systemctl restart docker
[root@dkengine2 ~]#

Now download the Container image using beneath command

[root@dkengine2 ~]# docker pull docker-repo.example.com:5000/ubuntu:16.04
16.04: Pulling from ubuntu
fec6b243e075: Pull complete
190e0e9a3e79: Pull complete
0d79cf192e4c: Pull complete
38398c307b51: Pull complete
356665655a72: Pull complete
Digest: sha256:6b079ae764a6affcb632231349d4a5e1b084bece8c46883c099863ee2aeb5cf8
Status: Downloaded newer image for docker-repo.example.com:5000/ubuntu:16.04
[root@dkengine2 ~]#

Now verify the image with ‘docker images‘ command

[root@dkengine2 ~]# docker images
REPOSITORY                            TAG                 IMAGE ID            CREATED             SIZE
docker-repo.example.com:5000/ubuntu   16.04               0ef2e08ed3fa        3 weeks ago         130 MB
[root@dkengine2 ~]#

That’s all from this article. I hope you guys got an idea how to setup own Docker Private Registry Server. If you like this article please don’t hesitate to share 🙂

11 thoughts on “How to Setup Docker Private Registry on CentOS 7.x / RHEL 7.x”

  1. Anders Jackson

    Good article, and it is posible to move this to Ubuntu, by using ufw(8) instead of firewall-cmd(8).

    But how do we secure the repository? Shouldn’t it be using https instead of http?

  2. Hi, I just followed through your post and found out the –insecure-registry setting does not work, maybe a hand?
    The setting is as follows:
    # cat /usr/lib/systemd/system/docker.service
    [Unit]
    Description=Docker Application Container Engine
    Documentation=https://docs.docker.com
    After=network-online.target firewalld.service
    Wants=network-online.target

    [Service]
    Type=notify
    # the default is not to use systemd for cgroups because the delegate issues still
    # exists and systemd currently does not support the cgroup feature set required
    # for containers run by docker
    ExecStart=/usr/bin/dockerd –-insecure-registry boot-node:5000
    ExecReload=/bin/kill -s HUP $MAINPID
    # Having non-zero Limit*s causes performance problems due to accounting overhead
    # in the kernel. We recommend using cgroups to do container-local accounting.
    LimitNOFILE=infinity
    LimitNPROC=infinity
    LimitCORE=infinity
    # Uncomment TasksMax if your systemd version supports it.
    # Only systemd 226 and above support this version.
    #TasksMax=infinity
    TimeoutStartSec=0
    # set delegate yes so that systemd does not reset the cgroups of docker containers
    Delegate=yes
    # kill only the docker process, not all processes in the cgroup
    KillMode=process
    # restart the docker process if it exits prematurely
    Restart=on-failure
    StartLimitBurst=3
    StartLimitInterval=60s

    [Install]
    WantedBy=multi-user.target

    also I have
    192.168.0.31 boot-node
    in /etc/hosts

    1. after I change “192.168.0.31 boot-node” to “192.168.0.31 boot-node boot-node” in /etc/hosts
      and change “/usr/bin/dockerd –insecure-registry boot-node:5000” to “/usr/bin/dockerd –insecure-registry=boot-node:5000” for ExecStart
      it starts to work

  3. By using this I am not able to push images getting the below response
    Get ‘https://x.x.x.x:5000/v2/:’ http: server gave HTTP response to HTTPS client

    1. Hi Nag,

      Did you update your system’s ‘/usr/lib/systemd/system/docker.service’ file and reload daemon service and restart Docker service ..?

    1. From any of the docker Engine node, run the “docker images” command to see the images inside your registry.

  4. Pradeep,

    how do we avoid docker push from trying to use a webproxy? in /etc/profile, I have explicitly set

    export no_proxy=”localhost,127.0.0.1,node2,*.local.domain”

    Yet when pushing image, docker tries to resolve the hostname through webproxy

    [admin@node2 ~]# cat /etc/hosts
    15.12.70.46 node2 node2

    # docker push node2:5000/friendlyhello
    The push refers to a repository [node2:5000/friendlyhello]
    983860a985da: Preparing
    fc5535ef2a0b: Preparing
    0bd3f73f5940: Preparing
    63d42cb10c64: Preparing
    32d47307f796: Preparing
    c86aa07d5fdb: Waiting
    d8a33133e477: Waiting
    Error: Status 404 trying to push repository friendlyhello: ….
    “>\nYour requested host \”node2\” could not be resolved by DNS.\n\n\n\n\n\n\n\n\n\n\nFor assistance, contact your network support team.\n\n\n\n\n\n\n”

  5. I would recommend using:

    systemctl edit docker.service

    Instead of editing the service file directly. I added the following lines (the first ExecStart= clears out the default, or you will have two and the unit won’t start)
    ———————————————-
    [Service]
    ExecStart=
    ExecStart=/usr/bin/dockerd -H fd:// –containerd=/run/containerd/containerd.sock –insecure-registry docker.example.com:5000
    ———————————————–

    You may also want to do ‘export SYSTEMD_EDITOR=vim’ if you don’t want nano.

Leave a Comment

Your email address will not be published. Required fields are marked *