Safeguard
Security Guides•

Does the official Node.js Docker image include a non-root user?

Yes. The official Node.js images ship a user named node with uid 1000, but you still have to switch to it. How to do that and fix file ownership.

Safeguard Security Team
4 min read

Yes. The official Node.js Docker images create a user called node with uid 1000, but the container still runs as root until you switch with a USER instruction or the user flag. Add USER node near the end of your Dockerfile, and make sure the app files are readable by that account.

What the image gives you

The maintainers of the Node.js images document the node user as the intended unprivileged account. They also note it is neither a build-time nor a run-time dependency, so you can remove or rename it if your app does not rely on it.

The image does not turn it on for you. A bare FROM node:24-slim followed by CMD ["node", "server.js"] runs your server as root inside the container. Root in a container is not root on the host in the normal case, but it widens what an attacker can do after a code execution bug: write anywhere in the filesystem, bind low ports, and use any capability the runtime grants.

The two ways to switch

In the Dockerfile, set the user after the steps that need root:

FROM node:24-slim
WORKDIR /home/node/app
COPY --chown=node:node package*.json ./
RUN npm ci --omit=dev
COPY --chown=node:node . .
USER node
CMD ["node", "server.js"]

At run time you can override instead, with the user flag on docker run, or runAsUser in a Kubernetes security context. Doing it in the image is safer because every consumer gets the same default.

A numeric form such as USER 1000 is worth considering. Tools that check "is this user non-root" can verify a number without resolving a name from the passwd file.

Fixing the "permission denied" that follows

Most breakage after switching comes from file ownership, not from the user itself. Three common causes:

SymptomCauseFix
EACCES writing logs or cacheApp writes into a root-owned directoryWrite to /tmp or a volume owned by node
Cannot read copied filesCOPY made them root-ownedUse COPY with the chown flag, as above
npm global install failsGlobal prefix is root-ownedSet NPM_CONFIG_PREFIX to a directory under /home/node

The Node.js image docs suggest exactly that last fix: point the npm global prefix at a directory in the non-root user's home.

Changing the uid or name

If your platform expects a different uid, the image docs show how to rename or renumber the user on Debian based variants with usermod and groupmod, and on Alpine by deleting the user and recreating it with adduser. Do this in an early layer, before copying files, or ownership will not match.

Try it yourself

Run a quick check on any image you build: start it and run the id command inside it. If the output says uid 0, the switch did not take effect. A layered image where a later FROM resets the user is a common reason.

Where Safeguard fits

A non-root default is a configuration choice, not a vulnerability that a scanner reports. Safeguard's dependency scanning and SBOM generation cover what is inside the image and your lockfile, and policies and gates can fail a pull request on findings you choose. You can try a free scan on a repository.

Quick check

Is the node user created in every Node.js image variant?

The Node.js image documentation describes the node user for its images with uid 1000. Verify on the exact tag you use by running id node inside it, since variants and future releases can change.

Do I still need a read only filesystem if I use USER node?

They solve different problems. A non-root user limits what the process may write and do. A read only root filesystem blocks writes to the image layers entirely. Many teams use both, with a small writable temp directory.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.