Docker Registry Management
Tags: linux, docker, beginners
Published: 2023-03-08 03:11:03

## Introduction

A Docker registry is a place to store Docker images. There are two types of Docker registries

- Private registry 
- Public registry

Docker Hub is a popular public registry, but organizations often prefer to use their own private registry to store and manage their images as it provides more control over image access and security.

Docker registry management involves pushing and pulling images from a registry, as well as managing access control, security, and versioning. To facilitate these tasks, various Docker registry management tools are available, such as Docker Trusted Registry, Harbor, and JFrog Artifactory

👉 In this post, I will be testing Docker-Hub repository, Nexus Repository and then apply GitHub actions to build an image automatically (CI)

---

## Hands on Docker-Hub 

> 💡 If you don't have a dockerhub ID, you can refer to the steps mentioned over [here](https://docs.docker.com/docker-id/)
 
After logging in to our account in Docker hub, we need to head to 'repositories' and select 'create repository'



![Creat](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nh9ftvnso5r0ii60wvbe.png)


Creating a private repository


![Repo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u8kz9kao7iio3nm0ozjz.png)


Once the repository is created, we can confirm the repository name 


![Repo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uupzipvhox2p02tmsqmw.png)

Now back to our Linux terminal. I will be working on a new directory

```bash
mkdir /DockerFile_Root
cd /DockerFile_Root
```

Creating a simple test `index.html` file

```bash
cat "Test" > index.html
```

Creating a Dockerfile

```bash
vi Dockerfile

FROM nginx:latest
LABEL maintainer "Author <Author@localhost.com>"
ADD index.html /usr/share/nginx/html
```

Building this dockerfile

```bash
docker build -t mynginx:v1 ./

Successfully built a367f58de111
Successfully tagged mynginx:v1
```

Logging in to my docker hub

```bash
docker login
Username:
Password:
Login Succeeded
```

Pushing the image to our docker hub repository

```bash
docker tag mynginx:v1 waji97/myrepo:v1
docker push waji97/myrepo:v1
```

Deleting the local images and tags

```bash
docker rmi mynginx:v1
docker rmi waji97/myrepo:v1
```

Checking the repository from dockerhub


![Image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ttyny2v8d19tg0mj5cmw.png)


Now we can start a docker container on our local machine using this image from our dockerhub

```bash
docker run -d --name Mynginx_1 -p 80:80 waji97/myrepo:v1
Unable to find image 'waji97/myrepo:v1' locally
v1: Pulling from waji97/myrepo
.
.
Status: Downloaded newer image for waji97/myrepo:v1
c3eeab8e250c18e472f105356790368253eb60991532d0b9b786829f94bf6bbe
```

👉 We can see that it pulled from my repository

Checking the docker process and images

```bash
docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                NAMES
c3eeab8e250c        waji97/myrepo:v1    "/docker-entrypoint.…"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp   Mynginx_1

docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
waji97/myrepo       v1                  a367f58de111        10 minutes ago      142MB
```

We can also visit our nginx server 


![Test](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2dwqopt65t3u5bs9sx1o.png)


---

## Hands on Nexus Repository

Nexus repository is a popular open-source repository manager developed by Sonatype. Nexus provides storing & managing software components, access control and integration with tools like Jenkins and Docker. 

It was mainly used with Java projects and the repositories were accessible by an WEB UI. We will be using Nexus repository to build a private image repository using docker format.

There are three types of nexus repository:

- Hosted: a private repository within a company (uploads are only possible locally)
- Proxy: mirrors remote repositories (cache)
- Group: groups various types of repositories together


![Nexus](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d15nslmb7u16jmvh4ln8.png)


👉 Before starting the hands on, I recommend turning off swap memory using `swapoff -a`

We will start by creating a volume

```bash
docker volume create nexus_volume
nexus_volume
```

Next we will change the ownership for the data directory for this volume

```bash
chown 200:200 /var/lib/docker/volumes/nexus_volume/_data/
```

👉 We need to change this as not changing this could possibly incur push/pull errors later

Pulling the nexus image

```bash
docker pull sonatype/nexus3:latest
```

Now, we will create a new container for our nexus repo

```bash
docker run -d --name Nexus -p 8081:8081 -p 5000-5001:5000-5001 -v nexus_volume:/nexus-data sonatype/nexus3
```

👉 I would recommend to have atleast 3GBs of RAM in your host system for the above to actually run

```bash
docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                      NAMES
9c68a0f95437        sonatype/nexus3     "/opt/sonatype/nexus…"   3 seconds ago       Up 1 second         0.0.0.0:5000-5001->5000-5001/tcp, 0.0.0.0:8081->8081/tcp   Nexus
```

Now we need to copy the password from

```bash
cat /var/lib/docker/volumes/nexus_volume/_data/admin.password 
```
👉 Copy the password that is displayed

Navigating to the Nexus Repo Manager via our browser and logging in as 'admin' user 


![Admin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u5jlb33gjaourwdqckr1.png)

This will trigger a new 'change password' wizard. We can change our admin account password using this wizard

From settings, we will navigate to 'Blob Stores'


![Blobs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/12szhsv12okz66vngjea.png)

Creating a new blob to use as docker-registry


![Registry](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f207xxcht6q3vyjpem7u.png)

Now heading to "Repositories" and clicking on "Create repository"

![Create](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vj20uelx1quuyuuoewkx.png)


We need to select 'docker(hosted)' from here and set up as following


![Pull](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4wh347oi3o66i231n3wi.png)

After creating the above repository, we need to create another one named 'docker(proxy)'


![P](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/plbn1czhiju0rbrnzsbb.png)

![Pu](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aoe70e5w42ba6zw92ztb.png)

Finally we will create our 'docker(group)' repository as well


![Group](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cti2d602ppnw84i5nza9.png)






Adding all the members to our group


![Group](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/asy8zc604l3c1t9vilcw.png)



Now from the "Security" section, we will navigate to Realms



![Realm](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txww7q68r6qo3urjpics.png)


Adding the "Docker Bearer Token Realm"


![Realms](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4oa7bf440mknp4pcd1kj.png)

👉 Going back to our Linux terminal

We will add the following to our daemon JSON file

```bash
vi /etc/docker/daemon.json

"insecure-registries" : ["192.168.1.10:5000", "192.168.1.10:5001"]
```

> 💡 We had to add this as Nexus supports HTTPS but we are using HTTP


Reloading the daemon and restarting docker

```bash
systemctl daemon-reload
systemctl restart docker

docker start Nexus
Nexus
```

Now we can pull a test image for our nexus repository

```bash
docker pull 192.168.1.10:5000/hello-world
Using default tag: latest
latest: Pulling from hello-world
.
Status: Downloaded newer image for 192.168.1.10:5000/hello-world:latest
```

To confirm if this image was downloaded,


![Nexus](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/imriuqbspon3uejeubwk.png)

We will perform another test by tagging our existing 'alpine' image to our nexus repository

```bash
docker tag alpine 192.168.1.10:5001/myalpine:v1
```

Logging in to our repository

```bash
docker login 192.168.1.10:5001
Username:
Password:
Login Succeeded
```

Pushing the tagged image to our repository

```bash
docker push 192.168.1.10:5001/myalpine:v1
The push refers to repository [192.168.1.10:5001/myalpine]
7cd52847ad77: Pushed 

# Logging out
docker logout 192.168.1.10:5001/myalpine:v1
```

Confirming this push from the WEB UI


![UI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s5akocydfhw9k41m5zm4.png)

---

## Hands on GitHub actions (CI)

GitHub Actions is a powerful CI/CD tool for automating software development workflows. It allows developers to automate tasks, build, test, and deploy code directly from GitHub.

- Workflows are defined in YAML format and consist of Events and Jobs.
- Events are triggers that execute a workflow.
- Events can be configured to trigger on actions such as a push to a repository.
- Workflows can contain multiple Jobs.
- When multiple Jobs are present, parallel execution is the default behavior.
- A Runner is required to execute Jobs and is typically a container.

✨ WorkFlow:-
- Workflow: The entire workspace for building, deploying, and testing.
- Event: The trigger for a Workflow to run (when it executes).
- Job: The unit of work in a Workflow.
- Step: Defines the sequence of tasks that a Job should perform.
- Action: A pre-defined function (library) that performs a specific task.
Runner: A containerized instance used to execute a Workflow.


![Github Actions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l18vm55osrx2zh80fihe.png)

👉 I will be doing a short hands on in which we will use Github actions to automatically create a docker image and push it to the dockerhub repository

From GitHub, we need to create a new repository for testing Github actions


![Github](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0beb797jmgu570kubhn4.png)

Now from DockerHub


![Dockerhub](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7gx5clz8viyc8cnt51o5.png)

Now we will navigate to "My profile" => "Edit Profile" => "Security"

![KDK](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cnjiygjoxxzs2rrfwxoh.png)


From this section, we will create a new access token with Read, Write and Delete permissions


![Token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lh1448sm6bib0an1w3h9.png)

👉 Going back to Github

From our repository, we will head to settings and select


![Actions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/49sv7ps1q498v4qrn6bm.png)

We will make 2 new secrets, one contains your DockerHub username and the other should contain the Access Token that we created from Dockerhub


![Token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uqn1vni0m7852tw0dxwd.png)

Now from our Github repository, we will create a new Dockerfile and also add a test html file



![File](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2s6soo77wz0xoca0k7ao.png)

We will head to "Actions" and setup our custom workflow


![Configure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ggltbopcmrdglegkevn.png)

My workflow YAML file looks like this


![YAML](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bpq7q8bfzj00prij84g2.png)

👉 This file will build an image and push it automatically to Dockerhub using Dockerfile present in the Github repository's main branch

Upon committing this file, we will have a new workflows folder in our repository


![Workflow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5po51btxg8y2m4eu4oj4.png)


We can also check our actions section


![Dockerpush](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n6yhp59e15g0l7n5crv2.png)

To test if this actually worked, we will go to our Dockerhub repository

👉 Dockerhub test repository


![Tag](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j03hd43mm2d1fmsc6feg.png)


We will test this image from our Linux Terminal now

Creating a container using our image from Dockerhub

```bash
docker login

docker run -d --name Mynginx_1 -p 80:80 waji97/testrepo:latest
latest: Pulling from waji97/testrepo
.
.
Status: Downloaded newer image for waji97/testrepo:latest
6bd35189a8261f80ed6763bd75f78cb0172bd21a0abcdb871ffb047c0d9e9729
```

Testing from the browser


![WEB UI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ee1jyfrx912patozgo8f.png)


👉 We will now try changing our `index.html` file from Github and commit so that Github actions can actually integrate this automatically

Upon committing the changes, we will be able to see a new workflow


![Workflow2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nfru79j3ua5noifsrc3q.png)


Now from the Linux System, we will delete the container and the image. 

After deleting the current image, we will pull the latest image from our Dockerhub repository and create a new container using the image to check our results


![Final](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kzwbep5jerdys69g0tle.png)



✨ This is Continuous Integration 

---

## Conclusion

In conclusion, managing a Docker registry is an essential aspect of containerization. Dockerhub, Nexus Repository, and Github Actions CI are three popular options for Docker registry management, each with their own advantages and limitations ✔