1. Overview

In this tutorial, we’ll deploy Docker containers to Kubernetes and see how we can use local images for these containers. We’ll use Minikube to run the Kubernetes cluster.

2. Dockerfile

First of all, we need a Dockerfile to be able to create local Docker images. This should be simple because we’ll focus on the Minikube commands.

Let’s create a Dockerfile with just an echo command that prints a message:

FROM alpine 

CMD ["echo", "Hello World"]

3. docker-env Command

For the first approach, we need to make sure that Docker CLI is installed. This is a tool for managing Docker resources, such as images and containers.

By default, it uses the Docker Engine on our machine, but we can change that easily. We’ll use this and point our Docker CLI to the Docker Engine inside Minikube.

Let’s check this prerequisite and see if the Docker CLI is working:

$ docker version

The output should be similar to this:

Client: Docker Engine - Community
 Version:           19.03.12
 ...

Server: Docker Engine - Community
 Engine:
  Version:          19.03.12
  ...

Let’s proceed with the next steps. We can configure this CLI to use the Docker Engine inside Minikube. This way, we’ll be able to list the images available in Minikube and even build images inside it.

Let’s see the steps required to configure the Docker CLI:

$ minikube docker-env

We can see the list of commands here:

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://172.22.238.61:2376"
export DOCKER_CERT_PATH="C:\Users\Baeldung\.minikube\certs"
export MINIKUBE_ACTIVE_DOCKERD="minikube"

# To point your shell to minikube's docker-daemon, run:
# eval $(minikube -p minikube docker-env)

Let’s execute the command from the last line as it will do the configuration for us:

$ eval $(minikube -p minikube docker-env)

Now, we can use the Docker CLI to investigate the Docker environment inside Minikube.

Let’s list the available images with the minikube image ls command:

$ minikube image ls --format table

This prints a table with the images:

|-----------------------------------------|---------|---------------|--------|
|                  Image                  |   Tag   |   Image ID    |  Size  |
|-----------------------------------------|---------|---------------|--------|
| docker.io/kubernetesui/dashboard        | <none>  | 1042d9e0d8fcc | 246MB  |
| docker.io/kubernetesui/metrics-scraper  | <none>  | 115053965e86b | 43.8MB |
| k8s.gcr.io/etcd                         | 3.5.3-0 | aebe758cef4cd | 299MB  |
| k8s.gcr.io/pause                        | 3.7     | 221177c6082a8 | 711kB  |
| k8s.gcr.io/coredns/coredns              | v1.8.6  | a4ca41631cc7a | 46.8MB |
| k8s.gcr.io/kube-controller-manager      | v1.24.3 | 586c112956dfc | 119MB  |
| k8s.gcr.io/kube-scheduler               | v1.24.3 | 3a5aa3a515f5d | 51MB   |
| k8s.gcr.io/kube-proxy                   | v1.24.3 | 2ae1ba6417cbc | 110MB  |
| k8s.gcr.io/pause                        | 3.6     | 6270bb605e12e | 683kB  |
| gcr.io/k8s-minikube/storage-provisioner | v5      | 6e38f40d628db | 31.5MB |
| k8s.gcr.io/echoserver                   | 1.4     | a90209bb39e3d | 140MB  |
| k8s.gcr.io/kube-apiserver               | v1.24.3 | d521dd763e2e3 | 130MB  |
|-----------------------------------------|---------|---------------|--------|

If we compare it with the output of the docker image ls command, we see that both show the same list. This means that our Docker CLI is correctly configured.

Let’s use our Dockerfile and build an image from it:

$ docker build -t first-image -f ./Dockerfile .

Now that it’s available within Minikube, we can create a pod that uses this image:

$ kubectl run first-container --image=first-image --image-pull-policy=Never --restart=Never

Let’s check the logs of this pod:

$ kubectl logs first-container

We can see the expected “Hello World” message. Everything works correctly. Let’s close the terminal to make sure our Docker CLI is not connected to Minikube for the next example.

4. Minikube Image Load Command

Let’s see another approach for using local images. This time, we’ll build the Docker image outside of Minikube on our machine and load it into Minikube. Let’s build the image:

$ docker build -t second-image -f ./Dockerfile .

Now the image exists, but it’s not yet available in Minikube. Let’s load it:

$ minikube image load second-image

Let’s list the images and check if it’s available:

$ minikube image ls --format table

We can see the new image in the list. This means that we can create the pod:

$ kubectl run second-container --image=second-image --image-pull-policy=Never --restart=Never

The container starts successfully. Let’s check the logs:

$ kubectl logs second-container

We can see it prints the correct message.

5. Minikube Image Build Command

In the previous example, we loaded a pre-built Docker image to Minikube. However, we can also build our images inside Minikube.

Let’s use the same Dockerfile and build a new Docker image:

$ minikube image build -t third-image -f ./Dockerfile .

Now that the image is available in Minikube, we can start a container with it:

$ kubectl run third-container --image=third-image --image-pull-policy=Never --restart=Never

Let’s check the logs to make sure it’s working:

$ kubectl logs third-container

It prints the “Hello World” message as expected.

6. Conclusion

In this article, we used three different ways to run local Docker images in Minikube.

Firstly, we configured our Docker CLI to connect to the Docker Engine inside Minikube. Then, we saw two commands to load a pre-built image and build an image directly in Minikube.