In a self-built Docker container, I want/need to run applications under a specific UID and GID. Trying to use a UID:GID pair that does not exist on the host fails.
Remarks
- the intended UID:GID(s) do not necessarily exist on the Docker host/ namespace
- Kernel and dockerd run with user namespaces enabled
- UID:GID are dictated by hard external requirements, e.g., 26551:1000
- target UID:GID in the container should not depend on UIDs:GIDs on the host
- my build user, i.e., my own 'desktop user', has UID:GID = 1000:1000
- for user namespaces subuid & subgid are within 10000:14095
Minimal demo example: Setup and preparation
Dockerfile: User Creation
Thus, I started to create a user in the container's Dockerfile (ARG+ENV for easier triggering new build stages) - here as 26551:1000 including creating a ${HOME} dir
ARG USERID=26551
ENV runUID=${USERID}
ARG GROUPID=1000
ENV runGID=${GROUPID}
ARG USERNAME='testuser'
ENV runUSER=${USERNAME}
ARG groupNAME='testgroup'
ENV runGROUP=${groupNAME}
RUN groupadd -g ${runGID} ${runGROUP} && \
useradd -u ${runUID} -g ${runGID} -ms /bin/bash ${runUSER}
docker build
As I need to inject sensitive information during the build, I am running with BuildKit
> DOCKER_BUILDKIT=1 docker build --secret id=foo_file,src=secret/foo.file --progress=plain . -t testfoo:latest
container context
Navigating in the image as interactive container, the ${HOME} dir belongs to a UID:GID from my 'host-user''s subuid:subgid range
[root@e436d2050f67 /]# grep testuser /etc/passwd
testuser:x:26551:26551::/home/testuser:/bin/bash
[root@e436d2050f67 /]# ls -all /home
total 0
drwxr-xr-x. 1 root root 16 Aug 16 13:40 .
drwxr-xr-x. 1 root root 248 Aug 16 13:51 ..
drwx------. 1 12455 12455 64 Aug 16 13:40 testuser
which might be fair enough, as I do not really need ${HOME} (although I wonder how this would work out on other hosts with different subuid/subgid ranges?)
The problem
Switching users does not work
The problem is that, although the user exists in the container's passwd etc. I cannot switch to it; neither via chroot or su(do):
[root@e436d2050f67 /]# chroot --userspec=1000:26551 / id
chroot: failed to set group-ID: Invalid argument
However, switching to my 'host-user' works
[root@e436d2050f67 /]# chroot --userspec=1000:1000 / id
uid=1000 gid=1000 groups=1000
although I have not defined the user in the container but only dockerd would map the UID:GID.
I already tried gosu as alternative but the behaviour is the same, i.e. the user does not 'exist' in the container/the host.
[root@e436d2050f67 /]# gosu 26551:26551 id
error: failed switching to "26551:26551": invalid argument
[root@e436d2050f67 /]# gosu 1000:1000 id
uid=1000 gid=1000 groups=1000
Docker --user
Running the container under a given user fails as again the UID does not exist on the host
> docker run --user=26551 -it testfoo:latest /bin/bash
docker: Error response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "setup user: cannot set uid to unmapped user in user namespace": unknown.
Question
How can I run a process in a container under a UID that does not exist on the host, perhaps by mapping the container UID:GID to some subuid:subgid available on the host?
Addendum #1
- SELinux is disabled
- the issue seems to be related to what user:groups are actually available in the container
while I have not been able to switch with su or gosu to one of the users/groups defined/created in the container build, I could switch to my host user's UID:GID in the container
[root@5e5137b95434 /]# gosu nobody id
uid=99(nobody) gid=99(nobody) groups=99(nobody)
[root@5e5137b95434 /]# su --group=99 testuser id
su: group 99 does not exist
[root@5e5137b95434 /]# su nobody id
This account is currently not available.
[root@5e5137b95434 /]# su --group=120000 testuser id
su: group 120000 does not exist
[root@5e5137b95434 /]# gosu 26551:26551 id
error: failed switching to "26551:26551": invalid argument
[root@5e5137b95434 /]# cat /etc/group
root:x:0:
bin:x:1:
daemon:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
mem:x:8:
kmem:x:9:
wheel:x:10:
cdrom:x:11:
mail:x:12:
man:x:15:
dialout:x:18:
floppy:x:19:
games:x:20:
tape:x:33:
video:x:39:
ftp:x:50:
lock:x:54:
audio:x:63:
nobody:x:99:
users:x:100:
utmp:x:22:
utempter:x:35:
input:x:999:
systemd-journal:x:190:
systemd-network:x:192:
dbus:x:81:
testgroup:x:26551:
switching to host user, which is not explicitly defined in the container
[root@5e5137b95434 /]# gosu 1000:1000 id
uid=1000 gid=1000 groups=1000
[root@5e5137b95434 /]# gosu 1000:1000 whomai
error: exec: "whomai": executable file not found in $PATH
[root@5e5137b95434 /]# gosu 1000:1000 echo "testfooout" > /home/testuser/1000_1000
> host > ls -all /tmp/foo/1000_1000
-rw-r--r-- 1 120000 120000 11 Aug 21 10:02 /tmp/foo/1000_1000
> host > id
uid=1000(hartlocal) gid=1000(hartlocal) groups=1000(hartlocal),10(wheel),969(docker)
[root@5e5137b95434 /]# gosu 1000:1000 sleep 600
> host > cat /proc/5737/cmdline
sleep600
> host > ls -all /proc/5737/cmdline
-r--r--r-- 1 121000 121000 0 Aug 21 10:04 /proc/5737/cmdline