Building Containers in K8s without Docker

Due to the deprecation and removal of the Docker runtime in Kubernetes, the traditional method of accessing Docker through /var/run/docker.sock is no longer available. As a result, I had to explore alternative container build tools and eventually chose BuildKit. BuildKit is an open-source tool that allows for optimized and parallel builds of Docker images. This tool outperforms the traditional Docker build process by utilizing multiple cores and building stages in parallel, resulting in faster builds.

There are a few assumptions I am making in this article

  1. You have a K8s cluster setup already.
  2. You have Jenkins setup already.
  3. You have the kubernetes plugin configured for Jenkins.
  4. You have a git repository.

Jenkins file

 1repository = '<private repo>/kramins-build'
 2tag = 'latest'
 3
 4podTemplate(inheritFrom: 'default', 
 5   containers:[
 6       containerTemplate(name: 'buildkit', image: 'moby/buildkit:master', ttyEnabled: true, privileged: true),
 7   ], 
 8   volumes: [
 9       secretVolume(secretName: 'docker-config', mountPath: '/root/.docker')
10 ]) {
11   node(POD_LABEL) {
12       stage('Prepare') {
13           checkout scm
14       }
15       stage('Build Docker Image') {
16           container('buildkit') {
17               sh """
18                   buildctl build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=${repository}:${tag},push=true
19               """
20           }
21       }
22   }
23}

Command

buildctl build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=${repository}:${tag},push=true

This command utilizes BuildKit's build tool, buildctl, to build a Docker image. Buildkit leverages the standard docker configuration for authentication to repositories, which can be viewed through the mounted secret on line 9.

The options used are:

  • frontend dockerfile.v0 specifies the build frontend to use, in this case the Dockerfile.
  • local context=. sets the local context directory to the current directory.
  • local dockerfile=. sets the local Dockerfile to use to the one in the current directory.
  • output
    • type=image sets the output type to image so that is can be pushed
    • name=${repository}:${tag} sets the image name and repository.
    • push=true will push the image to the repository.

References