Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Kubernetes & Helm By James Joyner IV · · 8 min read

Kubernetes Error Guide: 'container has runAsNonRoot and image will run as root' — Fix It

Quick answer

Fix the Kubernetes 'container has runAsNonRoot and image will run as root' error: set a non-root UID, fix the image USER, and satisfy the securityContext.

  • #kubernetes
  • #troubleshooting
  • #errors
  • #security
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

The kubelet refuses to start a container because your securityContext demands a non-root process but the image is configured to run as root (UID 0). The kubelet checks the effective user before starting the container, sees a conflict between runAsNonRoot: true and an image whose USER is root (or unset, which defaults to root), and fails the container immediately.

The literal error appears in the pod events and container status:

Error: container has runAsNonRoot and image will run as root

The pod typically shows CreateContainerConfigError while this is in effect. This is a good guardrail — it stops a workload that was supposed to be non-root from silently running privileged. The fix is to make the container actually run as a non-root user: set a numeric runAsUser, build the image with a non-root USER, and ensure the filesystem permissions let that user run.

Symptoms

  • Pod is stuck with CreateContainerConfigError and never starts.
  • Events show container has runAsNonRoot and image will run as root.
  • The pod or namespace enforces runAsNonRoot: true (directly or via Pod Security admission).
  • The image has no USER line, or USER root/USER 0.
kubectl get pod api-0
NAME    READY   STATUS                       RESTARTS   AGE
api-0   0/1     CreateContainerConfigError   0          25s
kubectl describe pod api-0 | grep -A2 -i runasnonroot
  Warning  Failed  kubelet  Error: container has runAsNonRoot and image will run as root

Common Root Causes

1. Image has no USER (defaults to root)

Most base images run as root unless the Dockerfile sets a USER. With runAsNonRoot: true and no explicit UID, the kubelet sees the image will run as UID 0 and refuses.

kubectl get pod api-0 -o jsonpath='{.spec.containers[0].securityContext}'
{"runAsNonRoot":true}

runAsNonRoot: true says “must not be root” but nothing tells the kubelet which non-root UID to use, and the image defaults to root — conflict.

2. Dockerfile explicitly sets USER root

Some images set USER root (or USER 0) for build steps and never switch back to a non-root user for runtime.

USER root
ENTRYPOINT ["/app/server"]

3. runAsNonRoot set without runAsUser

Setting runAsNonRoot: true without a numeric runAsUser only works if the image already declares a non-root user. If it does not, you must supply the UID yourself.

4. Pod Security admission (restricted) enforcing it

The restricted Pod Security Standard requires runAsNonRoot: true. A namespace labeled with it injects the requirement even if your manifest did not, surfacing the same runtime error when the image is root.

kubectl get ns prod -o jsonpath='{.metadata.labels}'
{"pod-security.kubernetes.io/enforce":"restricted"}

5. A numeric UID that maps to 0

runAsUser: 0 (or a build that resolves the user to 0) still counts as root and trips the check.

Diagnostic Workflow

Step 1: Confirm the exact error

kubectl describe pod <POD> | grep -i 'runAsNonRoot'

Step 2: Inspect the effective securityContext

kubectl get pod <POD> -o jsonpath='{.spec.securityContext} {.spec.containers[0].securityContext}{"\n"}'

Check whether runAsNonRoot is set and whether a runAsUser is present.

Step 3: Find the image’s USER

docker image inspect <IMAGE> --format '{{.Config.User}}'

An empty result means root. A non-numeric name (e.g. appuser) is not enough for runAsNonRoot unless the kubelet can resolve it to a non-zero UID — prefer a numeric UID.

Step 4: Check namespace Pod Security level

kubectl get ns <NS> -o jsonpath='{.metadata.labels}'

Step 5: Apply a non-root UID and retry

kubectl patch deployment <DEPLOY> --type merge -p \
  '{"spec":{"template":{"spec":{"securityContext":{"runAsNonRoot":true,"runAsUser":10001,"runAsGroup":10001,"fsGroup":10001}}}}}'

Example Root Cause Analysis

A service is moved into a restricted namespace and every pod fails to start:

kubectl get pods -l app=api
NAME               READY   STATUS                       RESTARTS   AGE
api-64c8d9-7xk2p   0/1     CreateContainerConfigError   0          40s
kubectl describe pod api-64c8d9-7xk2p | grep -i runasnonroot
  Warning  Failed  kubelet  Error: container has runAsNonRoot and image will run as root

The namespace enforces restricted, which requires non-root:

kubectl get ns prod -o jsonpath='{.metadata.labels}'
{"pod-security.kubernetes.io/enforce":"restricted"}

Inspecting the image confirms it has no USER:

docker image inspect registry.example.com/api:1.8 --format '{{.Config.User}}'

Empty output means the image runs as root. The app writes only to /tmp, so a non-root UID is safe. Adding an explicit numeric user resolves it:

kubectl patch deployment api --type merge -p \
  '{"spec":{"template":{"spec":{"securityContext":{"runAsNonRoot":true,"runAsUser":10001,"fsGroup":10001}}}}}'
kubectl rollout status deployment api

The pods start 1/1 Running. The durable fix is to add USER 10001 to the Dockerfile so the image is non-root by default.

Prevention Best Practices

  • Build images with an explicit numeric USER (e.g. USER 10001) so they run non-root without relying on the manifest.
  • Prefer a numeric runAsUser over a username; the kubelet cannot always resolve a name to a UID at admission time.
  • Ensure the app only writes to paths the non-root user owns (use fsGroup for mounted volumes, emptyDir for scratch).
  • Test images under runAsNonRoot: true in CI so a root-only image is caught before it reaches a restricted namespace.
  • Adopt Pod Security restricted early so security requirements are visible during development, not at deploy time. See more in Kubernetes & Helm guides.

Quick Command Reference

# Confirm the error
kubectl describe pod <POD> | grep -i runAsNonRoot

# Effective securityContext
kubectl get pod <POD> -o jsonpath='{.spec.securityContext} {.spec.containers[0].securityContext}{"\n"}'

# Image's configured user (empty = root)
docker image inspect <IMAGE> --format '{{.Config.User}}'

# Namespace Pod Security level
kubectl get ns <NS> -o jsonpath='{.metadata.labels}'

# Set a non-root UID and roll out
kubectl patch deployment <DEPLOY> --type merge -p \
  '{"spec":{"template":{"spec":{"securityContext":{"runAsNonRoot":true,"runAsUser":10001,"fsGroup":10001}}}}}'

Conclusion

container has runAsNonRoot and image will run as root means the kubelet blocked a container because policy requires non-root but the image runs as UID 0. The usual causes:

  1. The image has no USER and defaults to root.
  2. The Dockerfile sets USER root/USER 0.
  3. runAsNonRoot: true is set with no runAsUser and a root image.
  4. A restricted Pod Security namespace injects the requirement.
  5. A numeric UID that resolves to 0.

Supply an explicit non-root runAsUser and, ideally, bake a non-root USER into the image. For ad-hoc triage, the free incident assistant can turn this describe output into the exact securityContext fix.

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.