Dockerfile ends with root as the selected user

After completing build steps that require root, set a non-root default user for the application.

Description

Leaving USER root in the final image runs container processes as root unless the runtime overrides it. Build steps may need root, but retaining that privilege for the application can increase the impact of a compromise.

Root inside a container does not automatically mean unrestricted host access. Capabilities, mounts and runtime isolation also determine the impact.

Potential impact

  • A compromised application can access a broader set of files and processes inside the container.
  • Sensitive host mounts or excessive privileges can extend the impact to host resources.

Remediation

  • Complete root-only tasks such as package installation or account creation before switching to an ordinary user.
  • Prepare the required non-root account in the final runtime stage and select it with USER. Grant access only to necessary files and directories.
  • Check both the image’s default user and deployment overrides, then test the application after the change.

Examples

These excerpts compare account creation and the default runtime user. Supply the application files and startup command separately.

Before

dockerfile
FROM alpine:3.22
USER root
RUN adduser -D appuser

Creating appuser does not switch users; the last user selection remains root.

After

dockerfile
FROM alpine:3.22
USER root
RUN adduser -D appuser
USER appuser

USER appuser changes the default user after account creation. Verify file permissions and runtime settings as well.

References