Private container images need registry credentials before a Kubernetes node can pull them for a Pod. An image pull secret stores those credentials as a kubernetes.io/dockerconfigjson Secret, letting the workload reference a registry login without putting the username and token directly in the Pod manifest.

kubectl create secret docker-registry builds the Docker config JSON that the kubelet can use during image pulls. The Secret must live in the same namespace as the Pod, and the --docker-server value must match the registry host in the image reference.

A disposable namespace and a single test Pod keep the check separate from application workloads. Use a pull-only registry token or robot account for the Secret, then verify that the Pod moves past the image pull and starts before copying the pattern into a Deployment or another controller.

Steps to create a Kubernetes image pull secret:

  1. Create a namespace for the private image test.
    $ kubectl create namespace app-private
    namespace/app-private created

    Use the application namespace instead of app-private when adding a pull Secret to an existing workload.

  2. Create the image pull Secret for the private registry.
    $ kubectl create secret docker-registry regcred --namespace app-private --docker-server=registry.example.com --docker-username=registry-user --docker-password='registry-token' --docker-email=ops@example.com
    secret/regcred created

    Use a pull-only token or robot account rather than a personal registry password. Avoid saving real registry credentials in shared shell history, screenshots, or support transcripts.

  3. Confirm that the Secret has the Docker config type.
    $ kubectl describe secret regcred --namespace app-private
    Name:         regcred
    Namespace:    app-private
    Labels:       <none>
    Annotations:  <none>
    
    Type:  kubernetes.io/dockerconfigjson
    
    Data
    ====
    .dockerconfigjson:  168 bytes
  4. Create a Pod manifest that references the private image and pull Secret.
    private-image-pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: private-web
      namespace: app-private
    spec:
      restartPolicy: Never
      imagePullSecrets:
        - name: regcred
      containers:
        - name: private-web
          image: registry.example.com/team/private-web:1.0
          command: ["sh", "-c", "echo private image pull ok; sleep 300"]

    The Secret name under imagePullSecrets must exist in app-private. Use the same field inside a Deployment, Job, CronJob, DaemonSet, or StatefulSet Pod template.

  5. Apply the Pod manifest.
    $ kubectl apply -f private-image-pod.yaml
    pod/private-web created
  6. Wait for the Pod to become ready.
    $ kubectl wait --for=condition=Ready pod/private-web --namespace app-private --timeout=120s
    pod/private-web condition met

    A Pod that stays in ImagePullBackOff or ErrImagePull usually needs the registry host, Secret namespace, token scope, or image name checked.

  7. Check the Pod status.
    $ kubectl get pod private-web --namespace app-private
    NAME          READY   STATUS    RESTARTS   AGE
    private-web   1/1     Running   0          1s
  8. Read the container output to confirm the pulled image started.
    $ kubectl logs private-web --namespace app-private
    private image pull ok
  9. Inspect the Pod events for a successful image pull.
    $ kubectl describe pod private-web --namespace app-private
    Name:             private-web
    Namespace:        app-private
    Status:           Running
    ##### snipped #####
    Containers:
      private-web:
        Image:         registry.example.com/team/private-web:1.0
        State:         Running
        Ready:         True
    ##### snipped #####
    Events:
      Type    Reason     Age   From     Message
      ----    ------     ----  ----     -------
      Normal  Scheduled  0s    default-scheduler  Successfully assigned app-private/private-web to worker-1
      Normal  Pulling    0s    kubelet  Pulling image "registry.example.com/team/private-web:1.0"
      Normal  Pulled     0s    kubelet  Successfully pulled image "registry.example.com/team/private-web:1.0"
      Normal  Created    0s    kubelet  Container created
      Normal  Started    0s    kubelet  Container started

    If the event reason is FailedToRetrieveImagePullSecret, ErrImagePull, or ImagePullBackOff, inspect the event message before changing the workload.
    Related: How to check Kubernetes events
    Tool: Kubernetes Events Timeline Analyzer

  10. Delete the test namespace when the pull check is finished.
    $ kubectl delete namespace app-private
    namespace "app-private" deleted

    Skip this command for a real application namespace. Delete only the test Pod and test Secret if the namespace contains other workloads.