Baeldung Pro – Ops – NPI EA (cat = Baeldung on Ops)
announcement - icon

Learn through the super-clean Baeldung Pro experience:

>> Membership and Baeldung Pro.

No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.

Partner – Orkes – NPI EA (cat=Kubernetes)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

1. Overview

Kubernetes is a widely adopted container orchestration tool that allows us to run container images using Pods. By default, Pods can pull public images without authentication. However, authentication with container registries is required to pull the images from private repositories.

Kubernetes works well with many container registries. In this tutorial, we’ll discuss two common methods for pulling images from private Docker Hub repositories. So, let’s begin.

2. Creating Kubernetes Secret

First, we must authenticate with the Docker Hub to pull a private image.

In the case of Kubernetes, we can create a Secret of type docker-registry and refer to it from other Kubernetes objects, such as Pod, Deployment, StatefulSet, etc.

To understand this, first, create a new namespace:

$ kubectl create ns baeldung-ns
namespace/baeldung-ns created

Afterward, let’s use the create secret command to create a docker-registry type Secret named baeldung-image-pull-secret in the baeldung-ns namespace:

$ kubectl create secret \
docker-registry baeldung-image-pull-secret \
--docker-username=<user-name> \
--docker-password=<password> \
-n baeldung-ns

In this example, –docker-username and –docker-password represent the username and password of the Docker Hub.

Finally, let’s verify that the Secret has been created in the baeldung-ns namespace:

$ kubectl get secret -n baeldung-ns
NAME                         TYPE                             DATA   AGE
baeldung-image-pull-secret   kubernetes.io/dockerconfigjson   1      11s

Now that our setup is ready, we’ll discuss how to use this Secret to pull a private image from the Docker Hub in the next section.

3. Referencing the Secret

In the previous section, we created a Secret named baeldung-image-pull-secret. Now, let’s use it to create the Pod object.

3.1. Using the imagePullSecrets

First, let’s create the pod.yaml file with the following contents:

apiVersion: v1
kind: Pod
metadata:
  name: baeldung-private-image
  namespace: baeldung-ns
spec:
  containers:
  - image: baeldung/baeldung-private-image:1.0
    imagePullPolicy: Always
    name: baeldung-private-image
    imagePullPolicy: IfNotPresent
  imagePullSecrets:
  - name: baeldung-image-pull-secret  # Kubernetes Secret refers to the Docker Hub credentials

In this example, the Pod object refers to the Docker Hub credential using the imagePullSecrets field.

We must use the correct secret name in the imagePullSecrets field; otherwise, the Pod fails to start and gives the ImagePullBackOff error.

Now, let’s create the Pod using the kubectl apply command:

$ kubectl apply -f pod.yaml -n baeldung-ns           
pod/baeldung-private-image created

Finally, let’s use the kubectl get command to check the status of the Pod:

$ kubectl get pods -n baeldung-ns                    
NAME                     READY   STATUS    RESTARTS   AGE
baeldung-private-image   1/1     Running   0          2s

Here, we can see that the Pod has been created and it’s running.

3.2. Using the default Service Account

In the previous example, we specified the imagePullSecrets at the Pod level. However, that isn’t a very efficient method when we want to associate the Secret with multiple Pod objects.

In such cases, we can specify the Secret at the ServiceAccount level, and Kubernetes will automatically use the imagePullSecrets for all Pods running under that service account.

To understand this, let’s patch the default service account:

$ kubectl patch serviceaccount default \
-p '{"imagePullSecrets": [{"name": "baeldung-image-pull-secret"}]}' \
-n baeldung-ns

Next, let’s create a pod.yaml file with the following configuration:

apiVersion: v1
kind: Pod
metadata:
  name: baeldung-private-image
  namespace: baeldung-ns
spec:
  containers:
  - image: baeldung/baeldung-private-image:1.0
    name: baeldung-private-image
    imagePullPolicy: IfNotPresent

An important point to note is that in this example, we haven’t specified the imagePullSecrets in the YAML configuration.

Lastly, let’s use the kubectl apply command to create the Pod and verify that it’s running:

$ kubectl apply -f pod.yaml -n baeldung-ns
pod/baeldung-private-image created

$ kubectl get pods -n baeldung-ns         
NAME                     READY   STATUS    RESTARTS   AGE
baeldung-private-image   1/1     Running   0          5s

Here, we can see that the Pod is in a healthy state.

In this section, we used the default service account as an example. However, the best practice is to use a dedicated service account in the production environment.

4. Conclusion

In this article, we discussed pulling private images from Docker Hub in Kubernetes.

Firstly, we created a Kubernetes Secret in a namespace to authenticate with the Docker Hub.

Then, we used the imagePullSecrets field at a Pod level to refer to the Secret.

Finally, we patched the default service account to use the imagePullSecrets for the Pods running under the default service account.