Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Make USER change the uid and gid of COPY'd files #7537

Closed
2 of 3 tasks
cyphar opened this issue Aug 12, 2014 · 18 comments
Closed
2 of 3 tasks

Proposal: Make USER change the uid and gid of COPY'd files #7537

cyphar opened this issue Aug 12, 2014 · 18 comments
Labels
area/builder kind/enhancement Enhancements are not bugs or new features but can improve usability or performance.

Comments

@cyphar
Copy link
Contributor

cyphar commented Aug 12, 2014

The current USER directive changes the user which every RUN directive executes under. However, file copying instructions such as ADD and COPY are always copied with the owner being root:root. This was originally added in 026aebd, in order to fix #2684 and #3950. However, this results in an inconsistency in the Dockerfile interface, since USER can modify some directives, but not all of them.

I propose that the COPY directive should change the owner of any copied file to be the uid of the current user (as set by the USER directive and found by parsing /etc/shadow in the container -- or failing that, just setting it to nobody [65534]) and the gid should be the primary gid of the current user (as found by parsing the /etc/shadow file in the container -- or failing that, just setting it to nobody [65534]).

NOTE: After discussing this proposal on the IRC, it was decided that ADD should not be modified along the lines of this proposal (since it must be supported and backward compatible until it is deprecated and removed). To this end, I am only proposing that COPY should be modified, due to it's relative newness and since there is nowhere near as many backward compatibility concerns as with ADD.


EDIT: I propose a modification to the above proposal, such that:

  • If the b.Config.User is set to an empty string, then the same method as used in libcontainer is applied -- syscall.Getuid() and syscall.Getgid() are used instead.
  • If b.Config.User does not exist in /etc/passwd, then the builder emits an error.

Does anyone have any objections with the above modification to the proposal?


To assist in the tracking of patchsets and pull requests which are required to implement this proposal:


/ping @shykes and others.

@cyphar cyphar changed the title Proposal: Make USER change the uid and guid of COPY'd files Proposal: Make USER change the uid and gid of COPY'd files Aug 12, 2014
@tianon
Copy link
Member

tianon commented Aug 12, 2014

+1; this would make it significantly easier to use USER effectively

@thaJeztah
Copy link
Member

+1 For making it more consistent and align better with user expectations. Sad that ADD won't be included, but for obvious reasons.

@shykes
Copy link
Contributor

shykes commented Aug 12, 2014

I am OK with this.

In general I would like everyone's opinion on how to deal with a situation like this, where we have to choose between 1) full reverse compatibility, and 2) a significant improvement to the user experience.

In this case we got "lucky" and can make an acceptable compromise thanks to the timing of the introduction of COPY... But that doesn't give us a general solution for the next case.

@thaJeztah
Copy link
Member

cough by adding versioning to the Dockerfile format? cough 😺

@shykes
Copy link
Contributor

shykes commented Aug 12, 2014

@thaJeztah are you volunteering to prepare a proposal?

@thaJeztah
Copy link
Member

@shykes see the link (#4907) but I wrote it quite a while ago and may need to update it a bit as I'm sure it contains some non-sense as well :)

Additionally, as it contains some strategic/policy stuff (enforce / don't enforce versioning?) Will require input from the Docker core members as well.

I won't be able to assist in implementing it though. Coding in Docker would be really out of my league at this moment (I do track the issues and try to 'follow' changes, purely out of interest). Having said that, I'm always open to help thinking :)

@cyphar
Copy link
Contributor Author

cyphar commented Aug 13, 2014

The proposal has been modified to deal with some edge cases (non-existent users) so that it is more consistent with the way libcontainer handles conversions from runconfig.User to a uid and gid.

@tianon
Copy link
Member

tianon commented Aug 13, 2014

I'm still +1 - anything less would be inconsistent with how USER works in practice. 😄

@pikeas
Copy link

pikeas commented Aug 20, 2014

+1. I proposed an extension to ADD at #6119, and this solution is almost as good. However, I recommend that COPY follow RUN, and accept either a simple string or an array of arguments: file, user, group, and permissions mask.

@cyphar
Copy link
Contributor Author

cyphar commented Aug 20, 2014

@pikeas Your proposal (at least, how I understand it) is not similar to the the RUN directive's JSON form. The RUN directive's JSON form is used to explicitly state the process that should be execve'd (not to provide optional arguments that affect how the RUN directive is interpreted). If we were to use your proposal, I would think that some form like COPY file {"user": "<user>", "group": "<group>", "mode": "<mode>"} would make more sense (since they are options which are optional and are distinct from the file being copied) but would also (unfortunately) be uglier.

But personally, I don't really like that particular idea because it now means that there is even more inconsistencies in the interface (you can choose what user you can COPY as inline, but not what user you RUN as -- and the like) as well as the fact that now you have a whole new optional argument that adds more magic to COPY (which is kind of the reason why COPY was added -- to remove the magic from ADD). Also there aren't (AFAIK) any directives which have arguments that will affect a directive in this manner (all directives are essentially treated equally, whereby the arguments to a directive do not actually affect how a directive functions).

But feel free to open a proposal and ask on the IRC, I might be incorrect in my assertions.

@sruffell
Copy link

Just adding my +1 as well.

Came upon this thread while searching for a way to change the owner (and in my case permissions) on a large collection of legacy files. My problem with changing the permission / mode in a separate run command is that I double the size of the image since it appeared one layer contained the initial files, then the next layer contained copies of all the files with the permissions changed.

Something like this would allow me to work around since the files are added with rw permission on the group of the user.

@kdomanski
Copy link
Contributor

+1
The storage cost of running a separate chown is very impractical in my deployments.

@sarath
Copy link

sarath commented Dec 23, 2014

👍
New to docker. ::excited:: But this one bummed me out. Lost a couple of hours trying to figure this out, seems reasonable to expect ownership after USER.

@masom
Copy link

masom commented Jan 2, 2015

👍

@cyphar
Copy link
Contributor Author

cyphar commented Jan 6, 2015

@crosbymichael has closed the implementation PR, because apparently some functionality is "in the works" that would allow for (among other things) this functionality.

@cyphar cyphar closed this as completed Jan 6, 2015
@sarath
Copy link

sarath commented Jan 6, 2015

@cyphar is there a issue id we can refer to/track progress?

@cyphar
Copy link
Contributor Author

cyphar commented Jan 8, 2015

@sarath I am not sure, it was discussed on #docker-maintainers quite recently. If worse comes to worse and you need this functionality, you can use my patches (#9046) to patch your own version of Docker. N.B This is universally considered as a bad idea, because it will require you to update my patches with upstream changes.

EDIT: I missed @thaJeztah's proposal (#9934).

@thaJeztah
Copy link
Member

@cyphar Oops sorry for that, I should probably have put pinged you there. @unclejack as well because he was assigned to carry it. 😄

dliappis added a commit to elastic/elasticsearch-docker that referenced this issue Oct 9, 2017
Ensuring all files under /usr/share/elasticsearch have GID=0 **and**
the same group permissions as those of the user is tricky. `-R`
options of `chmod`/`chgrp` increase the image size with a large layer
and introduce slowness in the build process. `tar` doesn't give us any
option to force `gid` while extracting and of course we'd still need to
match the group permissions.

One solution is to prepare the needed files using multi-stage
builds[1] in a separate stage. Unfortunately `COPY` will always use
0:0[2] overriding `USER`, so even if prepare the files at another
stage, we'll still need to mangle ownership+perms or COPY and then
extract an archive, which again increases image size.

docker-ce 17.09 introduced the `--chown`[3] parameter, which solves
this problem.

Move code to extract elasticsearch, adjust ownership + group
permissions, install x-pack and plugins to a stage
`prep_es_files`. This allows have a very clean stage to build the
final elasticsearch image, with a clean history and reasonable size.

IMPORTANT: With this commit, the minimum docker-ce version on the building
machine needs to be `17.09`.

[1]
https://docs.docker.com/engine/userguide/eng-image/multistage-build/
[2] moby/moby#7537 (comment)
[3] moby/moby#34263
@thaJeztah thaJeztah added area/builder kind/enhancement Enhancements are not bugs or new features but can improve usability or performance. labels Sep 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/builder kind/enhancement Enhancements are not bugs or new features but can improve usability or performance.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants