KubernetesのSecurityContextで「container has runAsNonRoot and image will run as root」を修正する

intermediate☸️ Kubernetes2026-05-31| Kubernetes 1.18以降、任意のクラウドプロバイダー(EKS、GKE、AKS)またはPodSecurityアドミッションやOPA/Gatekeeperで非rootポリシーを適用しているオンプレミスクラスター

Error Message

Error: container has runAsNonRoot and image will run as root (pod: "...", container: "...")
#kubernetes#security-context#runAsNonRoot#pod-security#container

エラーの内容

securityContextrunAsNonRoot: true を設定したマニフェストを適用したところ、Kubernetes がその場でポッドを拒否しました:

Error: container has runAsNonRoot and image will run as root (pod: "my-app-7d9f8b-xkp2q", container: "app")

ポッドは起動しません。kubectl get pods を実行すると、Error 状態で止まっているか、Pending のまま凍結しています。これは kubelet による強制拒否であり、コンテナのプルや実行すら試みません。部分的な実行もなく、ログも出ず、ただ死んだポッドがあるだけです。

発生原因

runAsNonRoot: true を設定すると、Kubernetes はコンテナが実行される UID を確認します。イメージの USER ディレクティブが存在しないか root(UID 0)に設定されており、securityContext に runAsUser を指定していない場合、kubelet はそれをブロックします。このチェックはコンテナ起動前に実行されるため、毎回クリーンに失敗します。

主に次の 3 つの状況が原因として挙げられます:

  • root をデフォルトとするアップストリームイメージ(nginx、redis、python、node)の使用
  • runAsNonRoot: true を自動的に注入するクラスター全体の PodSecurity ポリシーまたは OPA/Gatekeeper ルール
  • セキュリティ強化のために runAsNonRoot: true を追加したが、runAsUser と組み合わせるのを忘れた

修正方法 1:SecurityContext に runAsUser を追加する(最速)

使用する非 root UID を Kubernetes に指定します。0 より大きい任意の UID を選択してください — 1000 または 65534(nobody)が一般的な選択肢です:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000        # ← これを追加
        runAsGroup: 1000       # 任意だが推奨
        fsGroup: 1000          # 任意:ボリュームの所有権用
      containers:
      - name: app
        image: nginx:latest
        securityContext:
          runAsNonRoot: true
          runAsUser: 1000      # コンテナごとに設定することも可能
          allowPrivilegeEscalation: false

適用して確認します:

kubectl apply -f deployment.yaml
kubectl get pods -w

**注意:**公式の nginx を含む一部のイメージは、内部でポート 80 にバインドするため root が必要です。非 root UID を強制すると、セキュリティ拒否ではなくパーミッションエラーで起動時にコンテナが失敗します。代わりに非 root 用に作られたイメージを使用してください:nginxinc/nginx-unprivileged はポート 8080 で UID 101 として動作し、この securityContext でそのまま使用できます。

修正方法 2:イメージが実際に使用する UID を確認する

UID を決める前に、イメージが期待する内容を調べましょう。次の 2 つのコマンドを実行します:

# イメージをローカルで実行して実効ユーザーを確認
docker run --rm nginx:latest id
# uid=0(root) gid=0(root) groups=0(root)

# イメージマニフェストを確認
docker inspect nginx:latest | grep -i user
# "User": ""
# 空 = root がデフォルト

すでに非 root ユーザーがいる場合は、その UID を調べて使用します:

docker run --rm your-image:tag id
# uid=1001(appuser) gid=1001(appuser)

# securityContext での設定:
#   runAsUser: 1001

修正方法 3:非 root ユーザーを含むイメージを再ビルドする

ユーザーをイメージに組み込んでおけば、この問題に二度と対処する必要はありません。そのイメージを実行するすべてのクラスターで、securityContext のパッチなしに自動的に正しい UID が使用されます:

FROM node:18-slim

# 非 root ユーザーを作成
RUN groupadd --gid 1001 appgroup && \
    useradd --uid 1001 --gid appgroup --shell /bin/bash appuser

WORKDIR /app
COPY --chown=appuser:appgroup . .
RUN npm ci --only=production

USER appuser          # ← Kubernetes はここを参照する

CMD ["node", "server.js"]

ビルド、プッシュ、マニフェストを更新します:

docker build -t your-registry/my-app:v2 .
docker push your-registry/my-app:v2

マニフェストのイメージタグを更新して適用します。イメージがすでに宣言しているため、securityContext に runAsUser は不要です。

修正の確認

ポッドのステータスを確認し、コンテナ内部から UID を検証します:

# ポッドが Error/Pending ではなく Running になっているはず
kubectl get pods

# セキュリティエラーがないことを確認
kubectl describe pod my-app-xxx

# コンテナに入ってユーザーを確認
kubectl exec -it my-app-xxx -- id
# 期待値:uid=1000 gid=1000 groups=1000

# 簡単な代替方法:
kubectl exec -it my-app-xxx -- whoami

ポッドが実行中で、UID が非ゼロであれば完了です。

クラスターポリシーによるエラーの場合

自分で runAsNonRoot: true を記述していないのに、このエラーが発生することがあります。それはクラスターが強制しているためです — 通常は PodSecurity アドミッションまたは Gatekeeper によるものです。

# 名前空間に PodSecurity ラベルがあるか確認
kubectl get namespace my-namespace -o yaml | grep pod-security

# 出力例:
# pod-security.kubernetes.io/enforce: restricted

restricted PodSecurity 標準は、その名前空間内のすべてのポッドに runAsNonRoot: true を義務付けます。修正方法は同じです — runAsUser を追加するか、イメージを再ビルドします。制約がマニフェストではなくクラスターから来ていることを把握しておく必要があります。

クイックリファレンス

  • 最速の修正: runAsNonRoot: true と合わせて runAsUser: 1000 を追加する
  • ポート 80/443 のイメージ: 非特権バリアントに切り替える(例:ポート 8080、UID 101 の nginxinc/nginx-unprivileged
  • カスタムイメージ: Dockerfile に USER 1001 を追加する
  • 使用する UID: 0 より大きければ何でも可 — 1000、1001、65534 が一般的
  • やってはいけないこと: エラーを消すためだけに runAsNonRoot: true を削除しない — これには存在する理由がある

Related Error Notes