KhueApps
Home/DevOps/Fix 'User specified in Dockerfile does not exist' at runtime

Fix 'User specified in Dockerfile does not exist' at runtime

Last updated: October 06, 2025

Overview

Docker fails to start a container when the USER declared in the Dockerfile (or passed with --user) is not present in the final image. Typical causes:

  • The base image lacks that user/group.
  • You created the user in a builder stage but not in the final stage.
  • You used a username with COPY --chown before creating it.
  • You’re using a distroless or scratch image without /etc/passwd entries.

The fix is to ensure the user exists in the final image, or use a numeric UID/GID that does not depend on /etc/passwd.

Quickstart

  • Prefer numeric UID:GID in USER and COPY --chown.
  • Create the user in the final stage (not just the builder).
  • For distroless/scratch, use a numeric UID (commonly 65532) and avoid name-based lookups.

Minimal working example (Alpine)

This example creates a non-root user by UID/GID, sets file ownership safely with COPY --chown, and runs a simple script.

# Dockerfile
FROM alpine:3.20
ARG UID=10001
ARG GID=10001

# Create group and user
RUN addgroup -g ${GID} app && \
    adduser -D -h /home/app -u ${UID} -G app app

WORKDIR /app
COPY --chown=${UID}:${GID} app.sh /app/app.sh
RUN chmod +x /app/app.sh

# Use numeric UID:GID to avoid name lookup issues
USER ${UID}:${GID}
ENTRYPOINT ["/app/app.sh"]
# app.sh
#!/bin/sh
id
whoami || echo "no username for this UID"
echo "App running as non-root"
sleep 1

Build and run:

docker build -t demo-nonroot .
docker run --rm demo-nonroot

Diagnose the error

  1. Inspect the image’s configured user:
    docker inspect --format='{{.Config.User}}' IMAGE
    
  2. Override the user for debugging and check /etc/passwd and /etc/group:
    docker run --rm --user root -it IMAGE sh -lc 'cat /etc/passwd; cat /etc/group'
    
  3. If multi-stage is used, verify the user is created in the final stage (the last FROM).
  4. If COPY --chown is used, ensure the user/group exists before that instruction.

Common fixes

  • Create the user in the final stage with a stable UID/GID:

    FROM debian:stable-slim
    ARG UID=10001
    ARG GID=10001
    RUN groupadd -g ${GID} app && \
        useradd -r -u ${UID} -g app -d /home/app -m app
    USER ${UID}:${GID}
    
  • Use numeric IDs everywhere:

    USER 10001:10001
    COPY --chown=10001:10001 . /app
    
  • Multi-stage: don’t create the user only in the builder. Either recreate it in the final stage or copy entries:

    FROM debian:stable-slim AS builder
    RUN groupadd -g 10001 app && useradd -r -u 10001 -g app app
    
    FROM debian:stable-slim
    # Option A: re-create
    RUN groupadd -g 10001 app && useradd -r -u 10001 -g app app
    # Option B: copy passwd/group lines (same distro family)
    COPY --from=builder /etc/passwd /etc/passwd
    COPY --from=builder /etc/group /etc/group
    USER 10001:10001
    
  • Distroless/scratch: rely on numeric UID; do not assume /etc/passwd exists.

    FROM gcr.io/distroless/static:nonroot
    # Many distroless images include UID 65532 ("nonroot"). Prefer numeric UID.
    USER 65532
    ENTRYPOINT ["/app/my-static-binary"]
    

Platform-specific user creation

Base imageCreate groupCreate user
Debian/Ubuntugroupadd -g G appuseradd -r -u U -g app -d /home/app -m app
Alpineaddgroup -g G appadduser -D -h /home/app -u U -G app app
BusyBoxaddgroup -g G appadduser -D -H -u U -G app app
Distrolessn/a (no package manager)Use numeric UID (e.g., USER 65532)

U = desired UID, G = desired GID.

Example of a broken Dockerfile and fix

Broken: user is referenced but never created.

FROM alpine:3.20
USER app
ENTRYPOINT ["id"]

Run:

docker build -t broken . && docker run --rm broken
# error: user app not found

Fixed: create the user first and use numeric UID:GID.

FROM alpine:3.20
RUN addgroup -g 10001 app && adduser -D -h /home/app -u 10001 -G app app
USER 10001:10001
ENTRYPOINT ["id"]

Permissions and Kubernetes note

If you set runAsUser/runAsGroup in Kubernetes, the container still needs file permissions that match that UID/GID. Ensure volumes and working directories are writable by that UID:

# fragment
securityContext:
  runAsUser: 10001
  runAsGroup: 10001
  fsGroup: 10001

Pre-chown mounted paths or set appropriate permissions during image build.

Pitfalls

  • Creating the user in the builder stage only. The final stage won’t have it.
  • Using a username in USER or COPY --chown before creating it.
  • Assuming /etc/passwd exists (distroless, scratch). Use numeric UID.
  • Inconsistent UID/GID across environments causing permission mismatches on mounted volumes.
  • Relying on whoami; it fails without an /etc/passwd entry. Use id instead.

Performance notes

  • Prefer COPY --chown over a subsequent RUN chown -R; it avoids an extra layer and reduces I/O.
  • Create users with fixed UID/GID to avoid expensive recursive chown on startup.
  • Minimize file ownership changes by structuring COPY steps so that ownership is set during copy, not after.
  • Avoid installing user-management packages in final images; create users with base tooling or numeric UID when possible to keep images small.

Tiny FAQ

  • Can I just use USER root to avoid the error?
    • Yes, but it reduces security. Prefer a non-root UID/GID.
  • Do I need /etc/passwd for USER to work?
    • No if you use numeric UID:GID. Names require /etc/passwd and /etc/group entries.
  • What UID should I use for distroless?
    • Many images ship with UID 65532. Use USER 65532, or consult the image metadata.
  • How do I debug a failing image?
    • Override the user: docker run --user root -it IMAGE sh, then inspect passwd/group and permissions.

Series: Docker

DevOps