Docker Registry/Repository (Insecure)

Whenever we use docker image pull command to pull an official docker image, that image is downloaded from a docker registry hosted on a remote server on a remote location.

But what if we want to download or push these images from our own private registry instead of the docker registry or Docker Hub

This can be achieved using Docker Registry.

The Registry is a stateless, highly scalable server-side application that stores and lets you distribute Docker images. The Registry is open-source, under the permissive Apache license.

How to install the docker registry? Docker provides its own image named registry for this purpose. We need to pull this image and run a container using this image.

gaurav@learning-ocean:~$ docker container run -d -p 5000:5000 --name simple_registry registry
e3835d2ab35d7883f84db1c65cf6e7ef5b4e1a85cdd1e63bc452ee379f56fdee

In the above command, we are running the container using the registry image, we have provided a name for the container and a port. By default it listens on port 5000 and also we have not assigned any volume in this command, a volume will be created automatically by default.

gaurav@learning-ocean:~$ docker container ls
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                    NAMES
e3835d2ab35d   registry   "/entrypoint.sh /etc…"   11 seconds ago   Up 10 seconds   0.0.0.0:5000->5000/tcp   simple_registry
gaurav@learning-ocean:~$

Our container is running now. Now we want to check how many images are present in our registry at this point. For this just curl to this URL

gaurav@learning-ocean:~$ curl http://127.0.0.1:5000/v2/_catalog
{"repositories":[]}
gaurav@learning-ocean:~$

As you can see,there is no image present currently.

Now we will add an image to this registry.

First let us inspect our container and check the volume attached to our container.

 gaurav@learning-ocean:~$ docker container inspect e38
# few lines removed from output
 "Mounts": [
            {
                "Type": "volume",
                "Name": "e37eda0e6eab78298f050ea5b6abffec94cb49c59c87f6edb8d7aaad470fae70",
                "Source": "/var/lib/docker/volumes/e37eda0e6eab78298f050ea5b6abffec94cb49c59c87f6edb8d7aaad470fae70/_data",
                "Destination": "/var/lib/registry",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
# few lines removed from output

We can see the output of the inspect command and find the volume information in the format shown in the above output.

In case if our container stops by any chance and we want to run the container again then we can attach the same volume to the container using the above volume information.

Also notice that the driver in the above volume information is 'local' because our data will be stored on the local file system, there are also drivers available for remote cloud storage as well which we can use to store our data remotely such as AWS S3, Google Cloud, Azure etc.

Now coming back to pushing an image to the local registry.

gaurav@learning-ocean:~$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
ubuntu       latest    1318b700e415   7 days ago     72.8MB
redis        latest    aa4d65e670d6   11 days ago    105MB
nginx        latest    08b152afcfae   12 days ago    133MB
mysql        latest    c60d96bd2b77   12 days ago    514MB
registry     latest    1fd8e1b0bb7e   3 months ago   26.2MB
ubuntu       14.04     13b66b487594   4 months ago   197MB
gaurav@learning-ocean:~$

We will be pushing the redis image to the local registry.

Now we run the following command so that the image points to our local registry instead of the default docker hub registry.

gaurav@learning-ocean:~$ docker image tag redis 127.0.0.1:5000/redis
gaurav@learning-ocean:~$

As seen in the below image our image with the local registry tag is created.

gaurav@learning-ocean:~$ docker image ls
REPOSITORY             TAG       IMAGE ID       CREATED        SIZE
ubuntu                 latest    1318b700e415   7 days ago     72.8MB
127.0.0.1:5000/redis   latest    aa4d65e670d6   11 days ago    105MB
redis                  latest    aa4d65e670d6   11 days ago    105MB
nginx                  latest    08b152afcfae   12 days ago    133MB
mysql                  latest    c60d96bd2b77   12 days ago    514MB
registry               latest    1fd8e1b0bb7e   3 months ago   26.2MB
ubuntu                 14.04     13b66b487594   4 months ago   197MB
gaurav@learning-ocean:~$

Now we will push this image to our local registry.

gaurav@learning-ocean:~$ docker image push  127.0.0.1:5000/redis
Using default tag: latest
The push refers to repository [127.0.0.1:5000/redis]
262de04acb7e: Pushed
45f6df634253: Pushed
e46136075591: Pushed
11f991845040: Pushed
dd1ebb1f5319: Pushed
814bff734324: Pushed
latest: digest: sha256:1bd57e1a42b99ae53412b582784d0362fa8205243ce5f289cb4f76de2907cb97 size: 1574
gaurav@learning-ocean:~$

The image is pushed. Now let's verify if the image is pushed successfully or not. For verifying, curl to http://127.0.0.1:5000/v2_catalog, we see that our image has been pushed successfully.

gaurav@learning-ocean:~$ curl http://127.0.0.1:5000/v2/_catalog
{"repositories":["redis"]}
gaurav@learning-ocean:~$

Now let us delete the Redis image present on our local file system.

gaurav@learning-ocean:~$ docker image ls
REPOSITORY             TAG       IMAGE ID       CREATED        SIZE
ubuntu                 latest    1318b700e415   7 days ago     72.8MB
127.0.0.1:5000/redis   latest    aa4d65e670d6   11 days ago    105MB
redis                  latest    aa4d65e670d6   11 days ago    105MB
nginx                  latest    08b152afcfae   12 days ago    133MB
mysql                  latest    c60d96bd2b77   12 days ago    514MB
registry               latest    1fd8e1b0bb7e   3 months ago   26.2MB
ubuntu                 14.04     13b66b487594   4 months ago   197MB
gaurav@learning-ocean:~$ docker image rm 127.0.0.1:5000/redis:latest redis:latest
Untagged: 127.0.0.1:5000/redis:latest
Untagged: 127.0.0.1:5000/redis@sha256:1bd57e1a42b99ae53412b582784d0362fa8205243ce5f289cb4f76de2907cb97
Untagged: redis:latest
Untagged: redis@sha256:cd0c68c5479f2db4b9e2c5fbfdb7a8acb77625322dd5b474578515422d3ddb59
Deleted: sha256:aa4d65e670d6518e5da96ca9d1a76370a942970a8802e6d5cc6bcf058ab12ca7
Deleted: sha256:3bd00d38f5ca70200050477c527cc60cfdf82911d6fe03932e2bcae31a95cfa2
Deleted: sha256:22722fde392d188cfbe5bbd0c2451cc71cf5b000afc0e5114c1066bb5e113ec9
Deleted: sha256:38212b55ef525e86cd726cd83c1a82a6009c68d24771d6e93d439fdc88e66f0e
Deleted: sha256:188c498579cef37b65a93d6448c6b129fa07d5740fc213a18843ff22d80cd10d
Deleted: sha256:2117165cd53c98f13ec7af36c9d8acd239fc541c847efaccb49885decf615d68
gaurav@learning-ocean:~$

If we disconnect our internet and try to pull the same image again, we get the below error as the default registry is unreachable.

But we are able to download the image from the local registry.

gaurav@learning-ocean:~$ docker image pull 127.0.0.1:5000/redis:latest
latest: Pulling from redis
33847f680f63: Already exists
26a746039521: Pull complete
18d87da94363: Pull complete
5e118a708802: Pull complete
ecf0dbe7c357: Pull complete
46f280ba52da: Pull complete
Digest: sha256:1bd57e1a42b99ae53412b582784d0362fa8205243ce5f289cb4f76de2907cb97
Status: Downloaded newer image for 127.0.0.1:5000/redis:latest
127.0.0.1:5000/redis:latest
gaurav@learning-ocean:~$

A point to note here is that docker only allows secure registry which are secured using TLS with the exception of localhost.

To check this let us tag another image to the IP allotted to our local machine.

gaurav@learning-ocean:~$ docker image tag redis 192.168.1.11:5000/redis

When we try to push this image,we get the error message shown in the below image which tells us to use https instead of http.

gaurav@learning-ocean:~$ docker image ls
REPOSITORY             TAG       IMAGE ID       CREATED        SIZE
ubuntu                 latest    1318b700e415   7 days ago     72.8MB
127.0.0.1:5000/redis   latest    aa4d65e670d6   11 days ago    105MB
redis                  latest    aa4d65e670d6   11 days ago    105MB
nginx                  latest    08b152afcfae   12 days ago    133MB
mysql                  latest    c60d96bd2b77   12 days ago    514MB
registry               latest    1fd8e1b0bb7e   3 months ago   26.2MB
ubuntu                 14.04     13b66b487594   4 months ago   197MB
gaurav@learning-ocean:~$ docker image push 192.168.1.11:5000/redis
Using default tag: latest
The push refers to repository [192.168.1.11:5000/redis]
Get https://192.168.1.11:5000/v2/: http: server gave HTTP response to HTTPS client
gaurav@learning-ocean:~$

To allow get the docker to allow insecure location, we need to modify docker configuration as follows:

We need to create the daemon.json file locally and add the IP which we want to allow to the IP list.

We have created the file daemon.json as follows in /etc/docker directory:

gaurav@learning-ocean:~$ cat /etc/docker/daemon.json
{
        "insecure-registries": ["192.168.1.11:5000"]
}

Now we need to restart the docker service and our container which has stopped.

gaurav@learning-ocean:~$ sudo service docker restart
gaurav@learning-ocean:~$ docker container ls -a
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS                          PORTS     NAMES
e3835d2ab35d   registry   "/entrypoint.sh /etc…"   32 minutes ago   Exited (2) About a minute ago             simple_registry
gaurav@learning-ocean:~$ docker container start e38
e38
gaurav@learning-ocean:~$

Now if we push our image again -

gaurav@learning-ocean:~$ docker image push 192.168.1.11:5000/redis
Using default tag: latest
The push refers to repository [192.168.1.11:5000/redis]
262de04acb7e: Layer already exists
45f6df634253: Layer already exists
e46136075591: Layer already exists
11f991845040: Layer already exists
dd1ebb1f5319: Layer already exists
814bff734324: Layer already exists
latest: digest: sha256:1bd57e1a42b99ae53412b582784d0362fa8205243ce5f289cb4f76de2907cb97 size: 1574
gaurav@learning-ocean:~$

The image is pushed successfully! We can even pull this image from this insecure registry.