# Using Gitea as a private image repository

Previously we have written a simple API server that interacts with MongoDB, redis, and influxDB. We also managed to run our deployments on our Kubernetes cluster with the image pulled from docker.

Now let's try to create our own private image repository. The Gitea application we set up before has a container registry that is compliant with the [Open Container Initiative](https://opencontainers.org/). As such, we can push and pull docker images to our Gitea.

Prerequisites: we need to have SSL enabled on our Gitea application, check here to find out more on how to enable it.

## Pushing to a private repository

* My main PC is using Docker Desktop with WSL2. To push our image successfully, we must enable insecure-registries in the Docker desktop configuration.
    
    Under Settings -&gt; Docker Engine, add the following:
    
    ```json
    {
      "builder": {
        "gc": {
          "defaultKeepStorage": "20GB",
          "enabled": true
        }
      },
      "experimental": false,
      "insecure-registries": [
        "192.168.1.4:3000"
      ]
    }
    ```
    
    `192.168.1.4:3000` is the URL of our Gitea application. This can be a simple domain name such as `gitea.local` if the DNS record is added into the DNS server (e.g. on PiHole).
    
* Perform a login to save credentials, and enter the username and password used for Gitea login. Here I have an account name called `andre`.
    
    ```bash
    docker login 192.168.1.4:3000 --username andre --password *******
    ```
    
* Next, we need to tag the docker image before pushing. According to Gitea documentation:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1708794690587/3b3e1a11-b42c-4c4a-ac6a-e622f606c723.png align="center")
    
    We need to first tag our image according to the above format
    
    ```bash
    # tag with an image ID
    docker tag 9b0f43d3c161 192.168.1.4:3000/andre/api-server:1.0.1
    
    # tag when building image
    docker build -t 192.168.1.4:3000/andre/api-server:1.0.1 .
    ```
    
* Now we can push to Gitea as shown below
    
    ```bash
    # push to gitea
    docker push 192.168.1.4:3000/andre/api-server:1.0.1
    
    # to view all the list of images you have pushed
    curl -ik --user andre https://192.168.1.4:3000/v2/_catalog
    # output
    # {"repositories":["andre/api-server"]}
    ```
    
    ```bash
    # to view all the tags of image
    curl -ik --user andre https://192.168.1.4:3000/v2/andre/api-server/tags/list
    # output
    # {"name":"andre/api-server","tags":["1.0.1"]}
    ```
    
* [Here is a list of APIs](https://specs.opencontainers.org/distribution-spec/?v=v1.0.0#content-discovery) we can use to view the images we have pushed
    

## Pulling from a private repository

we are following their [guide here](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/)

we first create our `auth` value which comprises of &lt;username&gt;:&lt;password&gt; which is then baseb4 encoded. We use `-n` to prevent echo from adding extra newlines.

```bash
echo -n "andre:12345678" | base64
# output
# YW5kcmU6MTIzNDU2Nzg=
```

Next, we can create our `dockerconfig.json` to store our credentials secrets. The `"192.168.1.4:3000"` key is the IP and port where our image repository is located, we provide the credential info such as `username`, `password`, `email` and `auth`, which we had just encoded earlier into this JSON file.

```json
// dockerconfig.json
{
    "auths": {
        "192.168.1.4:3000": {
            "username": "andre",
            "password": "12345678",
            "email": "andre@mail.com",
            "auth": "YW5kcmU6MTIzNDU2Nzg="
        }
    }
}
```

Now we can parse this JSON file into base64 again.

```bash
base64 dockerconfig.json
# output
# eyJhdXRocyI6eyIxOTIuMTY4LjEuNDozMDAwIjp7InVzZXJuYW1lIjoiYW5kcmUiLCJwYXNzd29yZCI6IjEyMzQ1Njc4IiwiZW1haWwiOiJhbmRyZUBtYWlsLmNvbSIsImF1dGgiOiJZVzVrY21VNk1USXpORFUyTnpnPSJ9fX0=
```

using this output value, we can then create a `image-pull-secret.yaml` file and store this value under `data.\.dockerconfigjson`. The type of secret here is `kubernetes.io/dockerconfigjson`, which is used to authenticate with a container registry when pulling a private image.

```yaml
# image-pull-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name:  image-pull-secret
data:
  .dockerconfigjson:  eyJhdXRocyI6eyIxOTIuMTY4LjEuNDozMDAwIjp7InVzZXJuYW1lIjoiYW5kcmUiLCJwYXNzd29yZCI6IjEyMzQ1Njc4IiwiZW1haWwiOiJhbmRyZUBtYWlsLmNvbSIsImF1dGgiOiJZVzVrY21VNk1USXpORFUyTnpnPSJ9fX0= # dockerconfigjson is a base64 encoded string:  cat ~/.docker/config.json | base64 -w 0 
type: kubernetes.io/dockerconfigjson
```

Now we just need to include this secret in our `api-server.yaml` so that it knows to use this to authenticate our Gitea application

We can add `imagePullSecrets` it under the deployment `spec.template.spec`.

Change the `spec.template.spec.containers.image` to the one pointing to your private image repository as well

`image: 192.168.1.4:3000/andre/api-server:1.0.1`

```bash
# api-server.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server-deployment
  annotations:
    description: "this is my normal backend server deployment"
    version: "1.0"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: api-server
  template:
    metadata:
      labels:
        app: api-server
    spec:
      containers:
        - name: api-server-container
          image: 192.168.1.4:3000/andre/api-server:1.0.1 # update the link to image registry
          resources: # declare resources limits and request
            limits:
              memory: "512Mi"
              cpu: "1"
            requests:
              memory: "256Mi"
              cpu: "0.2"
          ports: # container ports exposed
            - containerPort: 8080
          envFrom:
            - configMapRef:
                name: homek8-configmap
            - secretRef:
                name: homek8-secret
      imagePullSecrets:
        - name: image-pull-secret
```

## Making deployments to k8s

Now we are ready to deploy to Kubernetes.

First, we need to ensure that we added our Gitea SSL certificate to our Kubernetes nodes. To do that, copy the `giteaCA.crt` over to our k8 nodes then update the ca-certificate:

```bash
sudo cp giteaCA.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
```

Next, we can create a namespace for deployment:

```bash
kubectl create namespace homek8-custom-registry
kubectl config set-context --current --namespace=homek8-custom-registry
```

Lastly, deploy

```bash
kubectl apply -f .
```

Now we can see the container being successfully pulled and created.
