How to switch user(su) in docker command

11/6/2020

l want to launch a container with non-root user, but l cannot modify the origin Dockerfile, Or l know l can do something like Run useradd xx then User xx in Dockerfile to achieve that. What l am doing now is modifying the yaml file like the following:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-pod
    image: xxx
    command:
        - /bin/sh
        - -c
        - |
          useradd xx -s /bin/sh;
          su -l xx; // this line is not working
          sleep 1000000;

when l exec into the pod, the default is still the root user, anyone can help with that? Thanks in advance!

-- Rosmee
kubernetes

2 Answers

11/6/2020

You need to use security context as like below

   securityContext:
     runAsUser: 1000
     runAsGroup: 3000
     fsGroup: 2000

Reference: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#podsecuritycontext-v1-core

enter image description here


EDIT:

If you wanted to change the user in you container than, you can add extra layer of dockerfile, check below

Add dockerfile layer,

   FROM <your_image>
   RUN adduser newuser
   USER newuser
   :       
   :

Now use above custom image in your kubernetes.

-- dahiya_boy
Source: StackOverflow

11/7/2020

+1 to dahiya_boy's answer however I'd like to add also my 3 cents to what was already said.

I've reproduced your case using popular nginx image. I also modified a bit commands from your example so that home directory for the user xxx is created as well as some other commands for debugging purpose.

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-pod
    image: nginx
    command:
        - /bin/sh
        - -c
        - |
          useradd xxx -ms /bin/bash;
          su xxx && echo $?;
          whoami;
          sleep 1000000;

After successfully applying the above yaml we can run:

$ kubectl logs my-pod
0
root

As you can see the exit status of the echo $? command is 0 which means that previous command in fact ran successfully. Even more: the construction with && implies that second command is run if and only if the first command completed successfully (with exit status equal to 0). If su xxx didn't work, echo $? would never run.

Nontheless, the very next command, which happens to be whoami, prints the actual user that is meant to run all commands in the container and which was defined in the original image. So no matter how many times you run su xxx, all subsequent commands will be run as user root (or another, which was defined in the Dockerfile of the image). So basically the only way to override it on kubernetes level is using already mentioned securityContext:

You need to use security context as like below

   securityContext:
     runAsUser: 1000
     runAsGroup: 3000
     fsGroup: 2000

However I understand that you cannot use this method if you have not previously defined your user in a custom image. This can be done if a user with such uid already exists.

So to the best of my knowledge, it's impossible to do this the way you presented in your question and it's not an issue or a bug. It simply works this way.

If you kubectl exec to your newly created Pod in the interactive mode, you can see that everything works perfectly, user was successfully added and you can switch to this user without any problem:

$ kubectl exec -ti my-pod -- /bin/sh
# tail -2 /etc/passwd
nginx:x:101:101:nginx user,,,:/nonexistent:/bin/false
xxx:x:1000:1000::/home/xxx:/bin/bash
# su xxx
xxx@my-pod:/$ pwd
/
xxx@my-pod:/$ cd
xxx@my-pod:~$ pwd
/home/xxx
xxx@my-pod:~$ whoami
xxx
xxx@my-pod:~$

But it doesn't mean that by running su xxx as one of the commands, provided in a Pod yaml definition, you will permanently change the default user.

I'd like to emphasize it again. In your example su -l xxx runs successfully. It's not true that it doesn't work. In other words: 1. container is started as user root 2. user root runs su -l xxx and once completed successfully, exits 3. user root runs whoami.

So the only reasonable solution is, already mentioned by @dahiya_boy, adding an extra layer and create a custom image.

As to:

@Rosmee YOu can add new docker image layer. and use that image in your kubernetes. – dahiya_boy 18 hours ago

yes l know that, but as i said above, l cannot modify the original image, l need to switch user dynamically – Rosmee 17 hours ago

You say "I cannot modify the original image" and this is exactly what custom image is about. No one is talking here about modifying the original image. It remains untouched. By writing your own Dockerfile and e.g. by adding in it an extra user and setting it as a default one, you don't modify the original image at all, but build a new custom image on top of it. That's how it works and that's the way it is meant to be used.

-- mario
Source: StackOverflow