Building Docker images with Kaniko

Mahdi Mallaki
ITNEXT
Published in
6 min readNov 1, 2023

--

Building a Docker image using Docker in Docker with reduced privileges using Kaniko

Photo by Venti Views on Unsplash

Introduction

Kaniko is a valuable project designed to simplify the process of building Docker images within a Docker container. At times, you may require an isolated environment for creating Docker images, and utilizing a Docker container can make this process more efficient. Kaniko’s executor can take your Dockerfile and project context, building your project similarly to how you would with the docker build command, but without relying on the Docker daemon. This makes it particularly suitable for environments where sharing the Docker daemon among build containers, as done in Jenkins worker machines, could pose security risks.

Kaniko

Kaniko is a popular project for building Docker images for your project inside a Docker container. Sometimes, you may need to create an isolated environment for building a Docker image, and using a Docker container makes it easier to establish that isolated environment. The Kaniko executor takes your Dockerfile and project context, building your project similarly to how you would with the docker build command, all without requiring you to mount the Docker daemon into the build container. It’s well-suited for environments where you want to avoid sharing the Docker daemon among the build containers, as doing so can lead to security issues.

Kaniko vs DinD

DinD (Docker in Docker) technology shares the host’s Docker daemon with the container it’s running in. This means that it has full access to Docker on the host, potentially impacting the host’s Docker environment, which can be really dangerous. But Kaniko is more secure because it doesn’t need access to the host’s Docker daemon inside the container, reducing potential security risks.

On the other hand, Kaniko is primarily useful for building a Docker image, while DinD has a broader range of uses, with building images being just one of them. You can perform various tasks with DinD, such as managing containers on the daemon host and monitoring their status.

Kaniko vs Buildpacks

Buildpacks are highly automated and aim to make image building easier, without requiring you to write a Dockerfile for your project. In contrast, Kaniko requires manual Dockerfile creation and configuration.

On the other hand, Kaniko is a more low-level project that allows you to customize your project extensively, making your build process highly customizable. In comparison, the level of customization in Buildpacks can be somewhat challenging and occasionally impossible.

You can refer to my other article, which covers Buildpacks and how to use them:

When to Use Kaniko

Kaniko offers a variety of features that can simplify your tasks. In the following scenarios, it’s advisable to opt for Kaniko:

  • Customized & Complex Dockerfile: If you need to dockerize a multi-programming language project or a monolithic application, Kaniko is a better choice. It allows you to define your Dockerfile exactly as you need it, providing the freedom to customize it to your specifications. In contrast, other alternatives like Buildpacks may not offer as much flexibility for customization.
  • Security Concerns: Kaniko excels at creating an isolated build process without requiring access to the Docker daemon. This ensures that your build environment remains secure and doesn’t interfere with other build containers, making it a suitable choice when security is a priority.

Kaniko Usage

Let’s assume I want to build a Docker image for my project. First, I need to create a Dockerfile. After that, I can build a Docker image using Kaniko for my project. You don’t need to install any additional tools except for Docker. Kaniko provides a Docker image capable of building your project inside a container, with all the necessary build tools already pre-installed.

$ git clone https://github.com/dstar55/docker-hello-world-spring-boot
$ cd docker-hello-world-spring-boot
$
$ docker run --rm \
-v $PWD:/workspace \
gcr.io/kaniko-project/executor:v1.14.0 \
--destination mylocalregistry:5000/test
$
$ docker run --rm mylocalregistry:5000/test

The image gcr.io/kaniko-project/executor:v1.14.0 is used for building your project. The executor module is responsible for obtaining your source code and creating a Docker image from it. Let me describe the other parameters of the build command:

  • -v $PWD:/workspace: I've mounted the source repository into the Kaniko container. Kaniko requires both the source code and the Dockerfile to build your project, and it's common practice to keep these two together.
  • --destination: This specifies the image name and tag. Kaniko will automatically export and push the final image to your desired destination. However, you'll need to provide additional details, but it seems like the text is incomplete.

There are some other configurations that are not required but important:

$ git clone https://github.com/dstar55/docker-hello-world-spring-boot
$ cd docker-hello-world-spring-boot
$
$ docker run --rm \
-v $PWD:/workspace \
-v ~/.docker/config.json:/kaniko/.docker/config.json \
gcr.io/kaniko-project/executor:v1.14.0 \
--context "/workspace" \
--dockerfile "/workspace/Dockerfile" \
--destination mallakimahdi/test
$
$ docker run --rm mallakimahdi/test

In the above usage, you can see that I built a Docker image and pushed it to DockerHub. You need to provide your credentials to Kaniko to enable the push. Let me describe the above parameters:

--context (default: /workspace): The context usually represents the root of your project. Typically, we place the Dockerfile at the project’s root to use the ADD instruction with files in the build context.

--dockerfile (default: /workspace/Dockerfile): This parameter specifies the path where the Dockerfile is located. It can be outside of the build context, but standard practice is to place the Dockerfile in the project’s root directory.

-v ~/.docker/config.json:/kaniko/.docker/config.json: You must provide your credentials to Kaniko to allow it to push the already built Docker image to the Docker registry. If you’re using DockerHub, you should mount this file since this registry requires authentication. However, if you’re using a local Docker registry, you don’t need to mount credential information.

Conclusion

Kaniko offers a secure and flexible solution for building Docker images in isolated environments. While it differs from alternatives like DinD and Buildpacks, Kaniko excels in scenarios requiring a custom and complex Dockerfile. Additionally, if you have security concerns and wish to isolate the build process without relying on the Docker daemon, Kaniko provides an ideal solution. Its ease of use and capabilities make it a valuable tool in the world of containerization and continuous integration.

GitHub

You can find all the diagrams and code used in this article in the following GitHub repository:

Support My Blog ☕️

If you have any feedback or suggestions for improving my code, please leave a comment on this post or send me a message on my LinkedIn. If you enjoy my technical blog posts and find them valuable, please consider to buy me a coffee at here. Your support goes a long way in helping me produce more quality articles and content.

--

--