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!
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
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.
+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.