docker icon indicating copy to clipboard operation
docker copied to clipboard

uid and gid as ENV variables

Open ikutergin opened this issue 6 years ago • 24 comments

Issues and Contributing

Is it possible to add uid and gid as ENV variables to have an ability to change it during the docker run? It would be very helpful to run container on the machine with another uid/gid for the jenkins user than 1000/1000 and when mount should be used.

ikutergin avatar Sep 09 '19 12:09 ikutergin

+1 not sure why its hardcoded to run under uid 1000..

zloveless avatar Oct 24 '19 23:10 zloveless

You don't need an ENV variable to change the user. That can be done at run time with flags like:

docker run --user 1001

UIDs tend to be set in the Dockerfile to ensure that by default the container doesn't run as root. You can always map the UID/GID of the container at run time to another ID.

If you'd like to dive more into it a good reference is here: https://medium.com/@mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf

dmc5179 avatar Oct 25 '19 04:10 dmc5179

By using --user option, we can change the uid to run the container. However, if the uid isn't included in the /etc/passwd, which is the case in most cases, we get errors including "I have no name!" described in the above Medium article. I understand we can't resolve this issue even if we can set uid/gid using ENV.

The issue here for me is that 1000 is the uid Linux system assigns first. The uid is already taken by a real user and if we attach a volume for the jenkins_home, we should make it writable to the user uid=1000 in the host system.

Do you think it is possible to change the uid used in the container to a more uncommon one, such ash 10000 or so? Then, I can create a user/group for jenkins in the host system with the ids.

ksato9700 avatar Oct 13 '20 10:10 ksato9700

You don't need an ENV variable to change the user. That can be done at run time with flags like:

Yes "I" need it. Running it in synology under docker DOES NOT work with flags. Every other docker image I used until I tried to use jenkins uses env variables. Don't see any issue doing that then.

Subtixx avatar Dec 24 '20 23:12 Subtixx

@Subtixx did you solve this?

vospascal avatar Jun 19 '21 15:06 vospascal

No, just resorted to using a VM instead.. Shame that they don't care.

Subtixx avatar Jun 19 '21 20:06 Subtixx

I think we could take a PR for this, it would require a test, and also needs a change to the script that runs on startup to crown the files to the new owner of required

FYI @dduportal

timja avatar Jul 18 '21 17:07 timja

Setting a user with a fixed UID inside an image is a good practise to ensure that there is NO dependency with the underlying host: it allows the image to have deterministic behavior ("immutable image" pattern).

It is recommended to use Docker named volumes to ensure that the UID is not an issue, instead of sharing a directory on the host (it is the same thing under the hood, but with named volume, Docker managed the UID, GID, mask and paths for you):

$ docker volume create jenkins_data
$ docker run --detach --name=jenkins --volume jenkins_data:/var/jenkins-home:rw <...> jenkins/jenkins:lts
# Access data from another temporary container when required. Write to current directory
$ docker run --name=backup-jenkins --rm --volume jenkins_data:/data:ro alpine tar xzf - /data > ./jenkins_backup.tgz

=> If you cannot use named volume, can you describe the issue you have with it please?

You can also rebuild you own flavor of the image as per https://github.com/jenkinsci/docker/issues/1017#issuecomment-882088022.

Creating the user on runtime (instead of buildtime) could be done but at the cost of additional complexity that need to be written and tested. It is not on the priorities, but anyone interested in contributing can.

Please keep in mind that:

  • The whole entrypoint script will have to be working with the plugins+ref creation into volume dir
  • The "create at runtime" requires running chmod/chown on each container startup. This can be slow if there are a lot of jobs in Jenkins, or if the underlying filesystem is slow
  • User Namespacing must keep working with the "runtime user creation" https://docs.docker.com/engine/security/userns-remap/

dduportal avatar Jul 19 '21 14:07 dduportal

Thanks for all that info @dduportal, also fyi @MarkEWaite

It sounds like the above should be documented as the recommended way? as there's a number of issues where people have hit this

timja avatar Jul 19 '21 15:07 timja

That is a really good point. I initially assumed that the existing documentation was enough (ref. 2nd part of https://github.com/jenkinsci/docker#usage), but in fact it could be greatly improved since end users are still facing issues: it means there is room for improvement. Any help on this is welcome, as I'm not a native English speaker and I fear that I might not write correctly.

dduportal avatar Jul 19 '21 17:07 dduportal

  • The "create at runtime" requires running chmod/chown on each container startup. This can be slow if there are a lot of jobs in Jenkins, or if the underlying filesystem is slow

chmod/chown could be run if uid is the different that set by parameter. it will be fast in most cases

ikutergin avatar Jul 20 '21 10:07 ikutergin

I doubt it will be that fast, once you get a lot of jobs it will take a long time.

Is there a reason that you don't want to use named volumes?

timja avatar Jul 20 '21 10:07 timja

As I understand, named volumes will produce files with ownership of user from container (uid/gid). For example, if I have jenkins user id 1000 in container, everything that was created by jenkins will have owner 1000 on the host machine. As the result host user with id 1000 can corrupt files. Am I wrong?

ikutergin avatar Jul 20 '21 11:07 ikutergin

@ikutergin yes, but inside the volume managed by docker (that is stored in /var/lib/docker/volumes/<volume id>/_data). Please note that you have to enable https://docs.docker.com/engine/security/userns-remap/ if the UID 1000 should be used on your host machine: it will allow to map the UID 1000 of the container to another UID on the host machine.

dduportal avatar Jul 20 '21 11:07 dduportal

@ikutergin what is the use case you have to would be incompatible with the named volume?

dduportal avatar Jul 20 '21 11:07 dduportal

@ikutergin yes, but inside the volume managed by docker (that is stored in /var/lib/docker/volumes/<volume id>/_data). Please note that you have to enable https://docs.docker.com/engine/security/userns-remap/ if the UID 1000 should be used on your host machine: it will allow to map the UID 1000 of the container to another UID on the host machine.

As I understand, userns-remap configured for whole system. If I have multiple independent containers on the host, all of them will use this option.

ikutergin avatar Jul 20 '21 11:07 ikutergin

Yes, but without any information on your use case it is only a hard guess. Can you describe what you want to achieve to help us understand please ?

Le 20 juil. 2021 à 13:23, ikutergin @.***> a écrit :

 @ikutergin yes, but inside the volume managed by docker (that is stored in /var/lib/docker/volumes//_data). Please note that you have to enable https://docs.docker.com/engine/security/userns-remap/ if the UID 1000 should be used on your host machine: it will allow to map the UID 1000 of the container to another UID on the host machine.

As I understand, userns-remap configured for whole system. If I have multiple independent containers on the host, all of them will use this option.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

dduportal avatar Jul 20 '21 11:07 dduportal

You don't need an ENV variable to change the user. That can be done at run time with flags like:

Yes "I" need it. Running it in synology under docker DOES NOT work with flags. Every other docker image I used until I tried to use jenkins uses env variables. Don't see any issue doing that then.

I can only repeat myself.

Subtixx avatar Jul 22 '21 17:07 Subtixx

This suggests you should be able to use named volumes with synology? https://community.synology.com/enu/forum/1/post/133301

timja avatar Jul 22 '21 19:07 timja

You don't need an ENV variable to change the user. That can be done at run time with flags like:

Yes "I" need it. Running it in synology under docker DOES NOT work with flags. Every other docker image I used until I tried to use jenkins uses env variables. Don't see any issue doing that then.

I can only repeat myself.

+1 to this issue. uid/gid needs to match that of the Jenkins container and uid/gid 1000 is very common.

sahilshah6196 avatar Sep 16 '21 10:09 sahilshah6196

+1 here as well. My org has centralized auth and 1000:1000 belongs to somebody. Because of the centralized auth, /etc/subuid and /etc/subgid already map users and are not available for docker userns-remap. I had to fork the repo and hack the Dockerfile for uid/gid, so I'm no longer pulling the official image. What bothers me is that there appears to be no way to pass in build-args for uid and gid via the Makefile. I wouldn't have to fork (and thereby track) the repo if there were even a way to do something that simple. Not only, but building LATEST_LTS doesn't actually build the same image as jenkins/jenkins:lts-jdk11. It builds 2.303 instead of 2.303.2, leading to lots of deprecation messages upon startup. So I have to specify JENKINS_VERSION and JENKINS_SHA for the build to boot. This is a lot to go through to keep asking what we want to achieve. We want to achieve a secure deployment. And for me that is also without having to hack a fork. I can make the sacrifice of building from source if there's a way to pass in uid and gid to make without hacking. An even more elegant solution would be to use the official images and pass in uid and gid at runtime. But that might take considerable rewiring. So I'd be happy just to be able to build from source and pass uid and gid to make if there were a way to do that besides hacking, even if that is less elegant that specifying at runtime.

cbcunc avatar Oct 12 '21 22:10 cbcunc

I can make the sacrifice of building from source if there's a way to pass in uid and gid to make without hacking

Hello @cbcunc , for what it's worth it, you can avoid hacking and specify the uid/gid through the "docker-bake.hcl" manifest file.

This "manifest" is used by the docker buildx bake command to get the correct build settings for a given image (path to dockerfile, build args, names, etc.). The Makefile is only a remnant from the past, kept for executing commands: it should not be used to persist informations.

You have an example of build arg already there: https://github.com/jenkinsci/docker/blob/master/docker-bake.hcl#L177-L182 which sets the build-arg from the value of the respective environment variables. You could add another with your expected uid/gid on the image you want to build, because it's exposed through build-args: https://github.com/jenkinsci/docker/blob/master/11/debian/bullseye/hotspot/Dockerfile#L34-L41 .

Would it help you?

dduportal avatar Oct 16 '21 08:10 dduportal

@dduportal, I had done something like this before your reply:

https://github.com/cznethub/jenkins-docker/commit/ffab6aa20f1bac3633ba132da920ba0ae552ec9a

and then ran:

export JENKINS_SHA=c4b8532e25a33001a3d8883d3cd87a664953ace239b486839b683065817d29cf
export JENKINS_VERSION=2.303.2
export LATEST_LTS=true
export JENKINS_REPO=myproject-jenkins
export JENKINS_USER=myproject-user
export JENKINS_GROUP=myproject-group
export JENKINS_UID=$(id -u ${JENKINS_USER})
export JENKINS_GID=$(getent group ${JENKINS_GROUP} | cut -d: -f3)
make build-debian_jdk11

to get it to work. Is that like what you are suggesting? I was thinking of generalizing this to the other *nix platforms, documenting it, and contributing back if you think that would be worthwhile.

cbcunc avatar Oct 26 '21 18:10 cbcunc

For those who need a different uid/gid, which one should it be?

If there would be a specific combination, we could try to file a PR which adds another build variant. But I guess we all need different combinations. e.g. containers running root-less on Openshift would need a docker build with uid=1001 and gid=0.

PR #1342 adds a build with uid:gid being 1001:0

build it with e.g.:

export JENKINS_VERSION=2.332.3
export JENKINS_SHA=$(curl -sL "https://get.jenkins.io/war-stable/${VERSION}/jenkins.war.sha256" | cut -d' ' -f1)
make build-rhel_ocp_ubi8_jdk11

flozzone avatar May 08 '22 07:05 flozzone