Lesson 24: Non-Root Users and Container Security Best Practices
Security should be a priority. By default, processes inside a Docker container run as the root user, which is a major security risk.
The Root Problem
If a malicious actor gains control of a container running as root, they might exploit a vulnerability in the Docker daemon or the Linux kernel to gain root access to the host machine.
Solution: The USER Instruction
The USER instruction in a Dockerfile sets the user (by name or UID) that will execute all subsequent commands (RUN, CMD, ENTRYPOINT).
Example: Creating and Using a Dedicated User
-
Create the user and group: dockerfile FROM alpine:latest
Create a non-root group and user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
Ensure the new user owns the application directory
RUN chown -R appuser:appgroup /app
Switch to the non-root user
USER appuser
The CMD will now run as 'appuser'
CMD ["node", "server.js"]
-
Using Pre-built Users: Many base images (like Node.js, Python, or Alpine) already provide non-root users you can switch to immediately, like
nodeorpython.dockerfile FROM node:20-slim
Switch directly to the user provided by the base image
USER node
WORKDIR /home/node/app COPY . .
CMD ["npm", "start"]
Other Security Tips
- Use Small Base Images: Use
alpineorslimimages instead of full OS images (e.g.,ubuntu) to minimize attack surface. - Use Multi-Stage Builds (Lesson 21): Eliminate unnecessary build tools from the final image.
- Restrict Capabilities: Use the
--cap-dropflag duringdocker runto remove unnecessary kernel capabilities from the container.