UID Model — restricted-v2 (Legacy)
| Applies to: OCP 4.11–4.19 | SCC: restricted-v2 |
hostUsers: true (default) |
How It Works
Under restricted-v2, OpenShift overrides the Containerfile USER
directive at pod admission time. The SCC’s runAsUser strategy is
MustRunAsRange, which:
- Reads the namespace annotation
openshift.io/sa.scc.uid-range(default:1000000000/10000) - If the pod spec does not set
runAsUser, injects the first UID from that range (e.g.,1000620000) - If the pod spec sets
runAsUserto a value outside the range, rejects the pod
The Containerfile USER 1001 is ignored. The process runs as a UID
like 1000620000 — a value the image author cannot predict.
Key Facts
- The random UID is always a member of GID 0 (root group). This is guaranteed by CRI-O on OpenShift.
- OpenShift 4.x auto-injects the random UID into
/etc/passwdinside the container. (On OCP 3.x this was manual.) - All pods in the same namespace get the same first UID by default. Different namespaces get different ranges.
- The
USERdirective in the Containerfile still matters for certification (RunAsNonRoottest) — it must not berootor0.
Containerfile Implications
Correct Pattern
FROM registry.access.redhat.com/ubi9/ubi-minimal:latest
RUN microdnf install -y nodejs npm && \
microdnf clean all
COPY --chown=1001:0 app /app
WORKDIR /app
# Directories the app writes to must be group-writable
RUN chgrp -R 0 /app/data /app/logs && \
chmod -R g=u /app/data /app/logs
# USER must be non-root for certification, but the actual
# runtime UID will be different (random, from namespace range)
USER 1001
EXPOSE 8080
ENTRYPOINT ["node", "server.js"]
Anti-Patterns
# ❌ USER root — rejected by restricted-v2, fails certification
USER root
# ❌ USER nginx — non-numeric, can't verify non-root
USER nginx
# ❌ Hardcoded file ownership to a specific UID
RUN chown -R 1001:1001 /app
# This fails because runtime UID is not 1001 — it's 1000620000.
# The process can't write to files owned by 1001 unless GID 0
# has write permission.
# ❌ Listening on port 80
EXPOSE 80
# Non-root UID cannot bind ports < 1024
What Happens at Runtime
Containerfile: USER 1001
↓
SCC admission: MustRunAsRange → inject UID 1000620000
↓
Container: Process runs as UID 1000620000, GID 0
/etc/passwd entry auto-created
Files must be accessible via GID 0