Kubernetes Error Guide: 'container has runAsNonRoot and image will run as root' — Fix It
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
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
CreateContainerConfigErrorand 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
USERline, orUSER 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
runAsUserover 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
fsGroupfor mounted volumes,emptyDirfor scratch). - Test images under
runAsNonRoot: truein CI so a root-only image is caught before it reaches a restricted namespace. - Adopt Pod Security
restrictedearly 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:
- The image has no
USERand defaults to root. - The Dockerfile sets
USER root/USER 0. runAsNonRoot: trueis set with norunAsUserand a root image.- A
restrictedPod Security namespace injects the requirement. - 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.
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.