## TL;DR
Add a non-root user in your Dockerfile and switch to it with USER before the app starts. Create the user in an early layer, fix ownership of the app files, and keep root-only steps before the switch. A container breakout from a non-root process is a much smaller problem than one from root.

## The query
```
how to use a non-root user in Dockerfiles
```

## Use this when
- You are writing a new Dockerfile and the app currently runs as root by default
- You are hardening existing images and want to drop privileges for the runtime process
- A scan flags your images for running as root
- You need your images to run on platforms that enforce non-root policies

## Not for
- Debugging permission errors by adding USER root back everywhere; fix the file ownership instead
- Changing the user your host daemon runs as; this is the in-container process user
- Multi-tenant isolation on its own; pair it with namespaces and seccomp for real boundaries
- Secrets handling; non-root does not hide env vars or mounted secrets from the process

## Steps
1. Create a dedicated user in the Dockerfile. Use a distro-appropriate command (useradd, adduser) with no login shell and no password, and give it a fixed UID so file ownership is predictable. Expected output: the user exists in the image, verifiable with `docker run --rm [image] id [username]`.
2. Set ownership on the app files. Run `chown -R [username]:[group] /app` (or your app dir) before switching users so the app can read its own files. Expected output: `docker run --rm [image] ls -l /app` shows the user owning the files.
3. Switch users near the end of the Dockerfile. Put `USER [username]` after all root-needed steps (package installs, directory setup) and before CMD or ENTRYPOINT. Expected output: the Dockerfile has USER as one of the last instructions.
4. Build and verify the running user. Build the image, run it, and check that the app process is not UID 0 with `docker exec [container] id`. Expected output: uid is your app user, not 0.
5. Test the app fully as that user. Writability, port binding (use ports above 1024), and log paths all need to work without root. Expected output: the app starts, serves traffic, and writes logs with no permission errors.
6. Enforce it in CI. Add a check that fails the build if the image's default user is root. Expected output: a pipeline gate that blocks root-by-default images from shipping.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst__TyYiU4JrCxGkphpXvZn_A
