uid 1000 is almost _always_ the first non-system user. I'd prefer to use some other user, since the first non-system user is also usually an administrator. Unfortunately, I can't change the user in a later image based on the jenkins image, because /var/jenkins_home is a volume, so I can't change the permissions on it and have them persist.
A much better choice would be uid 500... it's in the system user range, but well above the range where uids will likely be auto-assigned by installing packages.
Weird... I pulled it into my fork and it closed the issue here.
I don't think setting the user id to a different number is going to work for everybody either.
With any docker image you need a combination of running with -u and correct volume permissions.
For example https://groups.google.com/d/msg/docker-user/-q-bwfsvuJE/pIVCPCRiniAJ
Sure, but using a uid that is guaranteed to be in use on a large number of
systems (1000 is the start of the non system range for Debian, too, and
I'll bet everything derived from Debian, since there's no reason to change
it) seems like asking for trouble. The problem is that since it's used to
set permissions on a volume, I can't change it later.
The real problem is that docker doesn't give us a way of mapping container
uids to host uids.
On Jun 15, 2015 2:23 AM, "Carlos Sanchez" [email protected] wrote:
I don't think setting the user id to a different number is going to work
for everybody either.
With any docker image you need a combination of running with -u and
correct volume permissions.For example
https://groups.google.com/d/msg/docker-user/-q-bwfsvuJE/pIVCPCRiniAJ—
Reply to this email directly or view it on GitHub
https://github.com/jenkinsci/docker/issues/112#issuecomment-111965248.
I have added instructions to the readme to run as a different user in c8c95d1
With the right jenkins home volume permissions docker run -u 500 should work
There are several requests to change the UID #153, #154, #165, #177, #277 so I'm going to reuse this one.
If the default UID is changed to something else (<500, 10000,...?)
Less likely to match host user uid, which makes it easier to set permissions only for the docker container data
With -u some plugins fail because they expect the uid to exist in /etc/passwd (git, ssh,...) - Wouldn't be a bad idea to try to improve those plugins
Can be easily switched with -u 9999, only affects git/ssh as mentioned above
Breaks backwards compatibility, people with previous data would now need to run with -u 1000
Users mounting host volumes now need to create dirs with a different user that won't exist in the host
With -u some plugins fail because they expect the uid to exist in /etc/passwd (git, ssh,...) - Wouldn't be a bad idea to try to improve those plugins
To be clear, these are actually the programs of Git and SSH — not (just) Jenkins plugins wrapping the programs — that depend on a valid mapping from UID to username, and raise an error when the container is run by a UID which does not map to a user in the container.
Use a system UID for the jenkins user and system GID for the jenkins group. The value 386 should work for both. Provide documentation about building a custom image for Jenkins Docker users that encounter a collision.
The typical workflow to support a matching volume from the default image is:
jenkins group with a GID that matches Jenkins Docker imagejenkins user with a UID that matches the Jenkins Docker image, and assign this user to the jenkins group, created $JENKINS_HOME.It's reasonable to expect the creation of a jenkins user and group on the host system for typical usage, I'll suggest that it's better to set the jenkins UID and GID in the Jenkins Docker image to be within the system user UID range and system group GID range, respectively. Setting the UID and GID within the system ranges will avoid having the jenkins user display in GUI login screens (see here and here). Although Jenkins Docker should not be run on a server with a GUI environment in production, you can expect your users to try it out in desktop machines. (You can probably expect some users to run Jenkins Docker in "production" from desktop machines, too.)
The major Linux distributions' user- and group-creation tools increment starting from SYS_UID_MIN and SYS_GID_MIN (100 on major Linux distros). RedHat/CentOS have a lower SYS_UID_MAX and SYS_GID_MAX (499). Assuming it's unlikely a system will have greater than 100 system users and groups, a value between 200 and 500 should be fine.
Maybe check the FreeBSD registered UIDs and FreeBSD registered GIDs to get an idea of what other services might use to make a collision even more unlikely. (I realize this is for a Unix, not Linux, but all the more chance to avoid collision.)
For example uid=386 and gid=386 meet all of the criteria above.
With all this said, it is impossible to avoid a UID/GID collision in every possible scenario. The best Jenkins Docker project can do is pick a value with an unlikely collision, like 386, and provide clear documentation on how to deal with a collision. I described this process in #277 under the heading "More information on custom builds of Jenkins Docker (workaround 2):". (As a side note, kudos to the Jenkins Docker maintainers for exposing uid and gid as ARGs.)
Given the context of the discussion includes allocating a matching system uid/gid, I wanted to point out that the following assumption is not future-proof in that it does not scale:
Assuming it's unlikely a system will have greater than 100 system users and groups, a value between 200 and 500 should be fine.
An apocryphal Bill Gates statement come to mind:
No one will ever need more than 640K memory.
I am of the opinion that this project suffers from something of a multiple personality disorder in that it is trying to satisfy two use-cases with significant but not 100% overlapping concerns. These two use cases are:
The first use-case is executed quite well but it is so opinionated that the resulting image is simply not fit as a base image to be extended (see the VOLUME declaration and user/group creation) without some ugly hacks that result in unwanted layers and cruft on the filesystem.
I propose that the current jenkins image be split into two images. The first is the base with only the bare minimum required to start a jenkins process. I think this would include:
jenkins.war... and would specifically NOT include:
EXPOSE declaration(s)VOLUME declaration(s)USER declaration(s)I would be willing to back off of the no USER assertion if the image was setup with scripts for initally running as root and dropping down to a specified user/group (possibly creating it if needed) prior to executing the jenkins.war. This still seems a bit too opinionated to me, however.
The second image should map to the current image in that it would FROM the base and expose the default ports, create the default user/group, declare the JENKINS_HOME VOLUME and all that jazz.
Given Docker's guidelines for official images, all of this may be more appropriate in the jenkinsci/jenkins namespace as opposed to the jenkins (-> library/jenkins) namespace.
Such a split would allow for use-cases (with a little extra work, sure) such as attempted in #298
@dweomer "Scale" has many connotations and possible dimensions. Can you please be more precise about what you mean by this sentence?
This assumption is not future-proof in that it does not scale.
Also it appears your second comment got cut off, or was left incomplete.
@gotgenes yes, my fat fingers hit enter before I was done with my comment. I applied an edit even before I received an email for your response.
As for my use of "scale", what I mean to point out is that if many containerized runtimes adopt your very reasonable assumptions/proposals then we will soon venture into the realm of collision within the uid/gid namespace(s). This becomes even more likely/pronounced in environments running a broad range of services on systems with a centrally maintained set of posix accounts/groups. This is not a new problem but with the explosive growth and adoption of Docker I see us all accelerating towards such collisions/overlaps quite rapidly.
Prior to the advent of user namespace remapping in 1.10 I did agree that "uid 1000 is a horrible choice for the jenkins user". Utilizing this feature of the Docker engine, however, mitigates the issue at hand in that jenkins container data on the system will be owned by a uid/gid combination that does not map to a user/group on the system.
@dweomer I agree with all your points above. I admit surprise, though, that given FreeBSD's registry system, there's still plenty of available UIDs/GIDs. But the Docker universe has much wider potential, so I agree, a collision at some point is inevitable.
For Docker Engine at the moment, the only way to guarantee no UID/GID collision with the host is to build an image customized to the system on which the image will run. In the short term, though, picking a better default UID/GID ought to be good enough to avoid collisions for most Jenkins Docker users.
I also think you made a really constructive suggestion on trimming the Jenkins Docker image (JRE instead of JDK, no VOLUME, etc.). (Or would that technically be a _destructive_ suggestion? 😃 ) If you haven't already filed those recommendations in separate issues, I would do that, so those don't get lost.
I'd also would like to have the option to configure the UID/GID of the jenkins user.
Actually some Docker projects manage to do that, e.g. this GitLab image:
https://github.com/sameersbn/docker-gitlab#host-uid--gid-mapping
IIUC gitlab runs as root and then switches. That's an option already proposed in #225
I just spent a couple of hours trying to get jenkins to run in a docker container, but am now giving up. Having a default UID of 1000 is the blocker. We can run jenkins itself, but ssh refuses to run, and we can't get to our sources.
Another default UID would be better; 386 would be fine.
Would it also be an option to have the image update its internal /etc/passwd using the actual userid it is running under, so that git&ssh works?
@elygre Please see my comment on #277, especially the directions for building a custom image.
@gotgenes Yes, I realize I can build a custom image, and I think your comment has all the right information. Thanks for taking the time!
I "support" this issue, though, because I agree that uid 1000 is a bad choice for the official image, and I would like to see the official image improve.
(I'm mostly happily running a yum-install at the moment. Migrating to Docker will wait until there is a good Docker-image.)
:-1: on any requirement to run the image as root.
UID mismatch for all issues I've read so far are related to jenkins_home bind mount from host, which is a bad practice : one should rely on volumes so permissions are correctly managed based on image metadata (volume owner is set as jenkins by image). Bind mount move the permission check on end-user responsibility, which is source for many issues.
@ndeloof
UID mismatch for all issues I've read so far are related to jenkins_home bind mount from host, which is a bad practice : one should rely on volumes so permissions are correctly managed based on image metadata (volume owner is set as jenkins by image).
I don't understand what you are saying. I assuming by "volumes" you mean "data volumes where no explicit mount point has been provided" e.g.,
docker run -v /home/jenkins jenkins
This still binds to _somewhere_ in the host filesystem, though. This article provides a demonstration of this. So _somewhere_ on the host OS, files are getting written as UID 1000. This still represents a security issue when there is an existing default user at UID 1000.
If there's something I'm missing, please help me understand.
Also, just to be clear, mounting volumes to an explicit mount point is not bad practice, and is necessary in the use case of, for example, spinning up a jenkins container from an already existing jenkins configuration. This would be necessary when transferring between host machines, or upgrading to a new version of the jenkins image.
somewhere is managed by docker daemon (run docker volume ls).
Main difference with bind mount is a volume run in copy mode by default, i.e. it's initial content and permission is set from the image. So the volume is owned by jenkins user as set in image.
And yes, files are written with this ID on host, which may collide with an existing user, something that would happen with ANY user ID.
@ndeloof, thanks for your reply.
Main difference with bind mount is a volume run in copy mode by default, i.e. it's initial content and permission is set from the image.
Okay, this makes sense.
And yes, files are written with this ID on host, which may collide with an existing user, something that would happen with ANY user ID.
Agreed. I mentioned above [emphasis added]:
With all this said, it is impossible to avoid a UID/GID collision in every possible scenario. The best Jenkins Docker project can do is pick a value with an unlikely collision, like
386, and provide clear documentation on how to deal with a collision.
Since UID 1000 has a high likelihood of collision on popular host OSes, the users of of this project are requesting it be changed.
Doing this now will just prevent any upgrade for existing users.
Also, even I agree there's a risk to conflict with some host user, such user won't have access to /var/lib/docker/volumes (require root permission) to abuse this UID collision.
I changed the uid/gid by making a new image that modifies the jenkins user's gid, uid, and home, and makes that home a new volume. (This is necessary because you cannot chown or chmod /var/jenkins_home because it is a volume.) Maks sure to do -v volname:/var/lib/jenkins instead of -v volname:/var/jenkins_home
FROM jenkins/jenkins:2.89.4
USER root
ENV JENKINS_HOME /var/lib/jenkins
ENV COPY_REFERENCE_FILE_LOG=/var/lib/jenkins/copy_reference_file.log
RUN groupmod -g 800 jenkins
RUN usermod -u 800 jenkins
RUN mkdir "${JENKINS_HOME}"
RUN usermod -d "${JENKINS_HOME}" jenkins
RUN chown jenkins:jenkins "${JENKINS_HOME}"
VOLUME /var/lib/jenkins
USER jenkins
As a note for further readers, one issue users have to handle is to bind mount a jenkins_home volume, which has to be owned by uid 1000 so jenkins container can access it. In some circumstances they might not have flexibility to choose the owner of this persistent volume.
A potential workaround, I suggest giving https://github.com/lebokus/docker-volume-bindfs a try to create a volume using bindfs, mapping actual uid to 1000 before bind mount.
I changed the uid/gid by making a new image that modifies the jenkins user's gid, uid, and home, and makes that home a new volume. (This is necessary because you cannot chown or chmod /var/jenkins_home because it is a volume.) Maks sure to do
-v volname:/var/lib/jenkinsinstead of-v volname:/var/jenkins_homeFROM jenkins/jenkins:2.89.4 USER root ENV JENKINS_HOME /var/lib/jenkins ENV COPY_REFERENCE_FILE_LOG=/var/lib/jenkins/copy_reference_file.log RUN groupmod -g 800 jenkins RUN usermod -u 800 jenkins RUN mkdir "${JENKINS_HOME}" RUN usermod -d "${JENKINS_HOME}" jenkins RUN chown jenkins:jenkins "${JENKINS_HOME}" VOLUME /var/lib/jenkins USER jenkins
works for me!!! Thanks.
Most helpful comment
I changed the uid/gid by making a new image that modifies the jenkins user's gid, uid, and home, and makes that home a new volume. (This is necessary because you cannot chown or chmod /var/jenkins_home because it is a volume.) Maks sure to do
-v volname:/var/lib/jenkinsinstead of-v volname:/var/jenkins_home