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
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
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
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 🙂
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?
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
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
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
Hi Nag,
Did you update your system’s ‘/usr/lib/systemd/system/docker.service’ file and reload daemon service and restart Docker service ..?
how can we get the list of all the images inside a registry?
From any of the docker Engine node, run the “docker images” command to see the images inside your registry.
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”
I’m a little confused about the firewall command. Should we need to be opening up port 5000 instead of 80?
You should allow port ‘5000’ in firewall as docker registry is running on 5000 port.
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.