HomeDockerDocker Images Without Docker - A Practical Guide

Docker Images Without Docker – A Practical Guide

The most well-known security flaw in Docker is that it requires root entry to construct your Docker images with the Docker daemon.

We have all read at least once that you should be careful using root entry. This tutorial will take a gaze at the downsides of using Docker and Docker alternatives to combat those, namely:

To understand why the Docker Daemon is operating with root entry and how this can become a dispute, we first have to understand the Docker architecture (at least on a high level). Container images are specified with the Dockerfile. The Dockerfile details how to construct an image based on your application and sources. Using Docker, we can use the construct command to construct our container image. Once you have the image of your Dockerfile, you can run it. Upon operating the image, a container is created.

Below is a simplified diagram of the Docker architecture, taken immediately from the official documentation.

Overview: Docker Architecture
Overview: Docker Architecture

The dispute with this is that you cannot use Docker immediately on your workstation. Docker is composed of a variety of different tools. In most cases, you will only interact with the Docker CLI. However, operating an application with Docker means that you have to run the Docker Daemon with root privileges. It actually binds to a Unix socket instead of a TCP port. By default, users can only entry the Unix socket using sudo command, which is owned by the user root.

The Docker Daemon is responsible for the state of your containers and images, and facilitates any interaction with “the outdoors world.” The Docker CLI is merely used to translate instructions into API calls that are sent to the Docker Daemon. This allows you to use a native or remote Docker Daemon.

Running the Docker Daemon regionally, you risk that any process that breaks out of the Docker Container will have the same rights as the host operating system. This is why you should only belief your own images that you have written and understand.

The next section will discuss alternatives to Docker. All of the alternatives mentioned below can construct OCI suitable container images. OCI stands for Open Container Initiative, which is a project by the Linux Foundation with the goal to define open standards for operating system-level virtualization; more specifically, Linux containers. This includes the runtime specification and the image specification of containers. Scott McCarty discusses in detail how different container standards fit together; here are some of the benefits of using container standards:

  • Higher flexibility between tools. If you can just replace the Docker Daemon in your Kubernetes cluster without noticing a difference, does it matter which tool you are using?
  • Gain a better understanding of containers — what actually happens when you run a container?
  • Higher reliability on your infrastructure. The work that you have put into your existing infrastructure does not become obsolete when you choose to switch to different tools.

Buildah provides a CLI tool that allows users to construct OCI or traditional Docker images. Buildah can be used to create and run images from a Dockerfile and without. In our case, we are going to use Buildah to construct the image and Podman to run the image.

Relationship between Buildah & Podman

Buildah and Podman are complementary tools to construct and run containers. The main differentiation between the 2 tools is that Buildah focuses on building OCI container images while Podman specializes in the management of the full container lifecycle. The instructions used in Buildah are quite identical to Docker instructions. Buildah replicates the same instructions that are found inside a Dockerfile to allow users to construct images without a Dockerfile.

In comparability, Podman is focused on the full container lifecycle of OCI images but also helps other container standards. Summarising, it helps you to maintain and modify OCI images, such as pulling and tagging, and allows you to run, and maintain containers created from those images.

The main difference to note between both tools is the concept of a container. Buildah is highly identical to Docker in the way containers are constructed and managed. Comparing this to Podman, in Podman containers are meant to be lengthy-lived. This difference makes both tools complementary; Buildah can be used to create containers and Podman to handle those.

Furthermore, you cannot commit a Buildah container from inside Podman nor vice versa. This is mirrored in the way that instructions of both tools are used. For instance, the commit command works differently in Buildah and Podman containers.

Buildah Podman
Focus Container Creation Manage Containers; Entire Container Lifecycle
Container Management Similar to Docker Containers are meant to be lengthy-lived
Commands Mirroring Docker Commands in functionality Some instructions might be identical but have
different functionality
Image Standards Support OCI images Support OCI images

Getting initiated with Buildah and Podman

Buildah has a variety of different installation options (that you can easily get lost in). We run on Ubuntu 20.04 and followed these installation instructions:

Make sure that you replace the Version ID with your Ubuntu version (in case you are on Ubuntu) — in our case, this was 20.04.

To check that the installation was successful, check for Buildah images:

Next, we will  install Podman:

Once done we can run the following to verify that our installation was successful:

Let’s go ahead and construct an image with Buildah. For this, we are using the following repository. The repository already has a Dockerfile that we can use. However, you can also create or use your own.

Next, we are going to use Buildah to construct the image based on our Dockerfile.

You should now see the different steps of the Dockerfile executed.

Output building the image with Buildah

We can see the images constructed with Buildah by operating:

And run the container using Podman:

We can now view our application on localhost:8080. All Podman instructions are listed in their documentation.

Running Go application with Buildah and Podman

Kaniko was initiated and is maintained by Google. In quick, it is an open source tool that allows users to construct images even without granting it root entry. These images are constructed inside a container or a Kubernetes cluster. Unlike the Docker daemon, Kaniko executes all instructions inside the userspace.

There are several different ways to deploy and run Kaniko:

To run a container, Kaniko needs 3 arguments:

  • A Dockerfile
  • A Build Context: The directory containing a Dockerfile which Kaniko can use to construct your image — e.g. COPY in the Dockerfile should refer to a file in the construct context
  • The name of the registry to which the final image should be pushed

Getting initiated with Kaniko

We will use Kaniko inside a native Kubernetes Cluster, using MicroK8s. To get initiated with Kaniko and to follow the next steps, we assume that you have the following set-up:

Either a native Kubernetes Cluster or you are able to entry a remote cluster on your machine.

We are going to test Kaniko with an existing Dockerfile. The application we are going to use is a basic Go application. You can either clone the application or use your own app and Dockerfile.

Create a file called volume.yaml that will specify our PersistentVolume. This is used to run Kaniko inside of Kubernetes regionally.

Go ahead and paste the following into your file:

You will have to replace the path to your directory (the 1 where the files are at). The easiest way to do this is to run:

And copy and paste the file path.

Next, we need a second file that volume is mounted to:

Paste the following content:

Lastly, we need to give Kubernetes the specs on the pod it is supposed to run.

Add the pod.yaml file:

And paste the following content:

Modifications that you have to make to the pod.yaml file:

  • Please provide your Docker Hub account name and the repository to which you want to push.
  • Make sure that you include the right location to your Dockerfile. In our case, the Dockerfile is in the same repository as the yaml files.

Now that we have all of this prepared, we need to create the Kubernetes secret to allow Kaniko to push the Docker image to the Docker Hub; note that you can also use another registry.

  • <your-registry-server>  is: (https://index.docker.io/v1/ for DockerHub)
  • <your-name> is your Docker username.
  • <your-pword> is your Docker password.
  • <your-email> is your Docker email.

In our case, we had to put the values in quotes e.g. “anaisurlichs” for your username.

Next, we are going to create our persistent volume. Note that it is necessary that you create the secret first before you create the volumes and the pod.

Lastly, we are creating the pods:

Using Kaniko console output

You can now view the pod:

It took some time for us to determine out how to get initiated with Kaniko. In our case, we used Kaniko in Kubernetes. Alternatively, you could also use the Docker Daemon to run your container images. However, in this case, there would not be much of a difference between using Docker immediately. If you would nonetheless like to do this, you do not require any of the files listed above. Instead, you would just run the following command with identical parameters to what we have specified in pod.yaml.

First, we need a config.json file in our current directory that holds our Docker login:

On Ubuntu, you can encode your credentials with:

Use the encoded credentials inside your config.json file. Next, we can construct and push our Docker image using:

Note that this command might take a while to finish. Below is the anticipated output:

Kaniko console output

Buildah allows you to construct images without a Dockerfile. The flexibility of building images without Dockerfiles allows for the integration of other scripting languages into the construct process. Since Buildah does not rely on a Daemon but instead on a comprehensive API written in Golang, instructions can be translated into other tools.

In comparability, Kaniko can be run with and without root entry to construct a container image and push it to a registry. While Kaniko is supported by Google, Podman has been developed by RedHat. Both initiatives are actively maintained.

Additional differences that we have noticed while using both tools:

  • Depending on your operating system, it might be quite difficult to install any of the mentioned tools.
  • In case you are already using Kubernetes, Kaniko allows you to get initiated right away. However, you may have to invest some time into setting up the yaml files.
  • Podman and Buildah are quite intuitive to use and use identical instructions to those that are defined by Docker.
  • Additionally, Buildah has better tutorials and further documentation available, which might become handy in the lengthy term.
  • You can run both Kaniko and Buildah from inside a container. However, it is not as straightforward using Buildah.
  • We constructed the same image using Kaniko and then using Buildah to compare the image size; the image construct by Kaniko using Docker is about half the size of the 1 constructed by Buildah.

Image constructed with Buildah and Podman:

Image size constructed with Buildah and Podman

Image constructed with Kaniko:

Image size constructed with Kaniko

Overall, it depends on your use case and the tools that you are already using to construct and handle your containers. Generally, it would not make much sense to use Kaniko with Docker. However, if you are already closely using Kubernetes, then it would be an easy integration and a worthy alternative. In contrast, the combination of Buildah and Podman is a better alternative if you want to immediately replace Docker.

In this tutorial, we compared 2 different alternatives to using Docker immediately. Neither has been as easy to get initiated with as Docker. In summary, if you are already using Kubernetes, Kaniko would be a fine alternative; if not, we would prefer Buildah and Podman. As you can inform, which tool would provide the best alternative depends closely on your use case.

Are you using Docker or either of the alternatives detailed in this tutorial? Let us know about your experience in the feedback!


Most Popular