Building container images on Kubernetes with Kaniko

kaniko docker build Kubernetes

3 min read | by Jordi Prats

When trying to build container images on Kubernetes we might be tempted to use the Docker in Docker approach: To do this you'll need to:

  • Run a docker daemon on the nodes, either as a service or as a container runtime (which it is deprecated since 1.20)
  • Allow the Pod to communicate with docker's socket

This approach is considered a security risk and it should be avoided.

As alternative, we can use kaniko: It is a tool to build container images inside containers (hence, Kubernetes clusters)

What kaniko really provides is a container image with an application that we can use to build container images from several sources and then push it to one of the supported registries. To decide if we want to run it using docker or as a Pod on a Kubernetes clusters it is really up to us.

Let's assume we want to create a Pod that fetches a public git repository, builds the image and then pushed it to Docker hub:

First we'll have to create the credentials to be able to authenticate against Docker hub to be able to push a container image. To do so we can use the following command that creates a Kubernetes secret that will hold all the data we need:

kubectl create secret docker-registry demo-registry \
                        --docker-server=$REGISTRY_SERVER \
                        --docker-username=$REGISTRY_USER \
                        --docker-password=$REGISTRY_PASS \
                        --docker-email=$REGISTRY_EMAIL

For docker hub the docker server needs to be https://index.docker.io/v1/ so the actual command will look like this:

$ kubectl create secret docker-registry dockerhub-registry \
                        --docker-server=https://index.docker.io/v1/ \
                        --docker-username=username \
                        --docker-password=passw0rd \
                        --docker-email=whatever@email.cat
secret/dockerhub-registry created

We can now create the Pod that will fetch the main branch from pet2cattle/kaniko-demo repository, build the image to, finally, publish the container on docker hub as [jordiprats/demo-kaniko-build:kaniko]:

apiVersion: v1
kind: Pod
metadata:
  name: kaniko-demo-build
spec:
  containers:
  - name: kaniko
    image: gcr.io/kaniko-project/executor:latest
    args: [ "--dockerfile=Dockerfile",
            "--context=git://github.com/jordiprats/django-ampa.git#refs/heads/main",
            "--destination=jordiprats/ampa:kaniko" ]
    volumeMounts:
    - name: kaniko-secret
      mountPath: "/kaniko/.docker"
  volumes:
  - name: kaniko-secret
    secret:
      secretName: dockerhub-registry
      items:
       - key: .dockerconfigjson
         path: config.json
  restartPolicy: Never

Once we apply this definition, it will create the Pod, fetch the repository, build the container image and finally push it to the registry:

$ kubectl apply -f kaniko-demo-build.yaml 
pod/kaniko-demo-build created
$ kubectl get pods --watch
NAME                READY   STATUS              RESTARTS   AGE
kaniko-demo-build   0/1     ContainerCreating   0          3s
kaniko-demo-build   1/1     Running             0          7s
kaniko-demo-build   0/1     Completed           0          21s

We can check docker hub to check that the container image have been pushed.

You can find the Dockerfile used to build the container image and the Pod definition on the pet2cattle/kaniko-demo repository


Posted on 04/04/2022