Skip to main content

Non-root containers in Kubernetes

· 2 min read
Matej Jelluš

Container should be able to perform only a very limited set of operations and it is highly recommended to use different user from root. To achieve this both docker file and kubernetes config must be changed.

Create non-root container

Docker containers run by default with root privileges. Changing the configuration limits the processes that can be executed and adds an extra layer of security.

FROM node:16-alpine

RUN addgroup --gid 3000 --system juffgroup \
&& adduser --uid 2000 --system --ingroup juffgroup juffuser

USER 2000:3000

...

EXPOSE 3001

CMD [ "node", "dist/index.js" ]

Define securityContext for Pod

When you want to ensure that no root container will run in your Kubernetes cluster, you can use securityContext for this. If you set runAsNonRoot to true, Kubernetes will check either runAsUser setting (also under securityContext) or USER directive defined in the image (must use numeric UID).

And while we are working with these settings, let's set other recommended policies straight away.

Containers are by default allowed to create, download or modify files. This can be misused by potential attacker. To prevent this, set readOnlyFilesystem to true and the filesystem of the container is read-only. If your application needs to write into filesystem, it is recommended to mount secondary filesystem.

Remove all unnecessary capabilities unless the application really needs it with capabilities setting. You can then add a specific capability if needed.

apiVersion: apps/v1
kind: Deployment
metadata:
name: node-express-kubernetes-example-deployment
labels:
# app, tier, environment, ...
spec:
replicas: 2
selector:
# ...
template:
# ...
spec:
containers:
- name: node-express-kubernetes-example-application
image: registry.digitalocean.com/juffalow/node-express-kubernetes-example:latest
imagePullPolicy: Always
ports:
- containerPort: 3001
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
capabilities:
drop:
- all
env:
# variables
livenessProbe:
# liveness probe settings
readinessProbe:
# readiness probe settings

References

You can find working example here with basic Node application and k8s configs.

Official pages:

Tools:


Did you like this post? Was it helpful? I am always learning and trying new technologies. When I struggle with something and finally manage to solve it, I share my experience.