{{announcement.body}}
{{announcement.title}}

Docker Without Root Privileges

DZone 's Guide to

Docker Without Root Privileges

in this article, we discuss how to run Docker without root privileges in order to better manage security within your containers.

· Cloud Zone ·
Free Resource

Docker as Root

Docker runs its containers as root. But does your workload really needs root permissions? The answer is rarely. Still, your containers, by default, continue to run as a root-user. This could have serious security concerns. A process that runs inside the container as root is in fact a process running as root on the host itself. This provides an opportunity for a malicious attempt to gain unrestricted access to the host itself.

You can check it by yourself, just use the following command on any image that you commonly use:

Shell
 




xxxxxxxxxx
1


 
1
$ kubectl run -i --tty hello-world --image=hello-world --restart=Never -- sh
2
/ # ps aux
3
PID   USER     TIME  COMMAND
4
  1   root     0:10  sh




Clearly, as a best practice, we should avoid running containers as root. So, how do we fix this, let us see how we can run a container as non-root user.

Add a Non-Root User to Dockerfile

Create a user with only as many permissions as is required by the workload inside the container. You can create a user with RUN command in the Dockerfile of the container’s image itself.

Dockerfile
 




xxxxxxxxxx
1


 
1
RUN groupadd --gid 5000 newuser \
2
    && useradd --home-dir /home/newuser --create-home --uid 5000 \
3
        --gid 5000 --shell /bin/sh --skel /dev/null newuser




The above line of code creates a user, newuser, together with a home and shell for the user. Now, simply add the user in your Dockerfile, like the following example:

Dockerfile
 




xxxxxxxxxx
1


 
1
FROM ubuntu:18.04
2
COPY . /myapp
3
RUN make /myapp
4
...
5
USER newuser
6
CMD python /myapp/hello.py




From line 5 onward, every command is run as newuser and not as root. Simple, isn’t it?

But, we do not always make use of only our custom images; we also use many third-party images, and we won't be able to inject an unprivileged user into them like above.

These third-party Docker images will run as root user by default, unless we do something about them. If you use an image from a not-so popular source, then it may even be embedded with a malicious command, which could compromise the security of your cluster.

Kubernetes pod security context and pod security policies come to our rescue.

You may also like: Securing Your Docker Containers.

Use Pod Security Context

You may use a Pod Security Context to restrict the execution of a Pod to a particular non-root user. To specify these security settings for a Pod, add a securityContext field in Pod specification.

YAML
 




xxxxxxxxxx
1
21


 
1
apiVersion: v1
2
kind: Pod
3
metadata:
4
  name: my-pod
5
spec:
6
  securityContext:
7
    runAsUser: 5000
8
    runAsGroup: 5000
9
  volumes:
10
  - name: my-vol
11
    emptyDir: {}
12
  containers:
13
  - name: my-container
14
    image: hello-world
15
    command: ["sh", "-c", "sleep 10 m"]
16
    volumeMounts:
17
    - name: my-vol
18
      mountPath: /data/hello
19
    securityContext:
20
      allowPrivilegeEscalation: false



In the above specification, runAsUser specifies that any container inside the pod will run with userID 5000 only. This is the user that we have created specifically as an unprivileged user. The runAsGroup specifies the group id of all processes. If we do not mention this, then the group ID will be root (0).

Now, you can create this pod and check the processes running inside the container:

Shell
 




xxxxxxxxxx
1


1
$ kubectl apply -f my-pod.yaml
2
$ kubectl exec -it my-pod – sh
3
ps
4
 
          
5
PID   USER     TIME  COMMAND
6
  1   5000     0:00  sleep 10 m
7
  6   5000     0:00  sh




As you can see above, the PID 1 is being run as userID 5000 and not as root.

Use Kubernetes Pod Security Policy

Kubernetes Pod Security Policy defines the conditions that a pod must run with; otherwise, it will not be provisioned in the cluster. In other words, if these conditions are not met, Kubernetes will prevent the pod from running.

A sample PodSecurityPolicy is given below: 

YAML
 




xxxxxxxxxx
1
28


1
apiVersion: policy/v1beta1
2
kind: PodSecurityPolicy
3
metadata:
4
  name: my-psp
5
spec:
6
  privileged: false
7
  #Required to prevent escalations to root.
8
  allowPrivilegeEscalation: false
9
  allowedCapabilities:
10
  - '*'
11
  volumes:
12
  - 'nfs'
13
  hostNetwork: true
14
  hostPorts:
15
  - min: 8000
16
    max: 8000
17
  hostIPC: true
18
  hostPID: true
19
  runAsUser:
20
    #Require the container to run without root.
21
    rule: 'MustRunAsNonRoot'
22
  seLinux:
23
    rule: 'RunAsAny'
24
  supplementalGroups:
25
    rule: 'RunAsAny'
26
  fsGroup:
27
    rule: 'RunAsAny'




This security policy achieves the following:

  • Restrict a container from running in privileged mode.
  • Restrict a container that needs a root.
  • Restrict a container that access esvolumes other than NFS volume.
  • Only allow containers to access host port 100.

Activate policy:

Shell
 




xxxxxxxxxx
1


1
$ kubectl create -f my-psp.yaml



Check the policy:

Shell
 




xxxxxxxxxx
1


1
$ kubectl get psp
2
NAME    PRIV   RUNASUSER         FSGROUP   SELINUX   VOLUMES
3
My-psp  false  MustRunAsNonRoot  RunAsAny  RunAsAny  [nfs]
4
 
          


Now that the policy has been created, you can test it by trying to run a container with root privileges.

Shell
 




xxxxxxxxxx
1


 
1
$ kubectl run --image=my-root-container



The pod security policy will disallow it to run and give an error message:

Shell
 




xxxxxxxxxx
1


 
1
$ kubectl get pods
2
NAME         READY    STATUS     
3
my-root-pod  0/1      container has runAsNonRoot and image will run as root
4
 
          



Conclusion

In this post, I have highlighted the inherent risk in running a Docker container under the default settings of a root user. I have also proposed multiple ways to overcome this risk.

  • If you are running a custom image, then create a new unprivileged user and specify it in your Dockerfile.
  • If you are using third party images then you can set security context at pod or container level.
  • Yet another way is to create a pod security policy that will not allow any container to run with root privileges.


Further Reading

Topics:
container security ,docker ,kubernetes security ,cloud ,security

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}