-
Notifications
You must be signed in to change notification settings - Fork 73
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
Fix using rocker for non-root containers #50
Conversation
If the base image given by the user does not have root privileges, building the rockerized image will fail. Extensions seem to expect that their Dockerfile snippets are executed with root privileges. This patch injects a `USER root` instruction right after FROM base_image. For similar reasons the `user` extension has to run last, because its snippet changes the active user again and subsequent snippets from other extensions might fail.
Yeah, the user already has special logic to execute at the end I think that it will always be special. And likely each snippet could do something like declare if it should be user or root and then we'd set and unset the user ID in the dockerfile. See #10 A generic way to declare dependencies would also be valuable to get both ordering and automatically inject prerequisies like --x11. I'd also like to try to support an argument like |
- A user with the same UID already exists in the container image. - A group with the same GID already exists in the container image. - A user with the same name already exists in the container image. In all those cases the existing user or group gets deleted before creating a new one. Changing the password and adding the user to the sudo group is redundant to creating /etc/sudoers.d/rocker.
I removed the redundant reordering of extensions in 9df8a8c. We also found that not all special cases were covered (054cbc4)
In all those cases the existing user or group gets deleted now before creating a new one. Changing the password and adding the user to the |
e22fcfd
to
c520a4e
Compare
Codecov Report
@@ Coverage Diff @@
## master #50 +/- ##
==========================================
+ Coverage 86.29% 86.31% +0.02%
==========================================
Files 7 7
Lines 591 592 +1
==========================================
+ Hits 510 511 +1
Misses 81 81
Continue to review full report at Codecov.
|
…userdel" This reverts commit c520a4e.
aa84cbc
to
fdb464c
Compare
…medir_helper The tool fails with exit code 6 if the top-level directory does not exist yet. (a39bc32231c8)root@c71fe951b480:/# getent passwd johannes johannes:x:1000006:1000:Johannes Meyer:/share/homes/johannes:/bin/bash (a39bc32231c8)root@a39bc32231c8:/# rm share -R (a39bc32231c8)root@a39bc32231c8:/# mkhomedir_helper johannes; echo $? 6 (a39bc32231c8)root@a39bc32231c8:/# mkdir share (a39bc32231c8)root@a39bc32231c8:/# mkhomedir_helper johannes; echo $? 0
fa9bb0b
to
8cee014
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for extending the support to more of the corner cases.
Do you have public example images that could be used as test cases for some of these corner cases?
I do not have one that I can share as-is, and also did not find a public example on Docker Hub. But I created a simple FROM ubuntu
RUN useradd docker
USER docker
CMD ["bash"] Without this patch: $ rocker --user meyerj/unprivileged
[...]
Building docker file with arguments: {'path': '/tmp/tmpjoilklgz', 'rm': True, 'nocache': False}
building > Step 1/5 : FROM meyerj/unprivileged
building > ---> 22d887b3ed36
building > Step 2/5 : RUN if ! command -v sudo >/dev/null; then apt-get update && apt-get install -y sudo && apt-get clean; fi
building > ---> Running in c9430b165011
building > Reading package lists...
building > E: List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied)
no more output and success not detected
Build failed exiting With this patch: $ rocker --user meyerj/unprivileged
[...]
building > Step 1/6 : FROM meyerj/unprivileged
building > ---> 22d887b3ed36
building > Step 2/6 : USER root
building > ---> Using cache
building > ---> 5a200b7615ba
building > Step 3/6 : RUN if ! command -v sudo >/dev/null; then apt-get update && apt-get install -y sudo && apt-get clean; fi
building > ---> Using cache
building > ---> 3e286e07cd50
building > Step 4/6 : RUN existing_user_by_uid=`getent passwd "1000006" | cut -f1 -d: || true` && if [ -n "${existing_user_by_uid}" ]; then userdel -r "${existing_user_by_uid}"; fi && existing_user_by_name=`getent passwd "johannes" | cut -f1 -d: || true` && if [ -n "${existing_user_by_name}" ]; then userdel -r "${existing_user_by_name}"; fi && existing_group_by_gid=`getent group "1000" | cut -f1 -d: || true` && if [ -z "${existing_group_by_gid}" ]; then groupadd -g "1000" "johannes"; fi && useradd --no-log-init --no-create-home --uid "1000006" -s "/bin/bash" -c "Johannes Meyer,,," -g "1000" -d "/home/johannes" "johannes" && echo "johannes ALL=NOPASSWD: ALL" >> /etc/sudoers.d/rocker
building > ---> Using cache
building > ---> 0e80cb597379
building > Step 5/6 : RUN mkdir -p "$(dirname "/home/johannes")" && mkhomedir_helper johannes
building > ---> Using cache
building > ---> 03cfd1c13f33
building > Step 6/6 : USER johannes
building > ---> Using cache
building > ---> 17794f1d1625
building > Successfully built 17794f1d1625
Executing command:
docker run -it --rm 17794f1d1625
johannes@3a3b8efd5ac5:/$ Even without $ rocker --nvidia meyerj/unprivileged
[...]
running, docker run -it --rm f31d2d29af59
output: standard_init_linux.go:211: exec user process caused "permission denied"
/tmp/detect_os failed:
> standard_init_linux.go:211: exec user process caused "permission denied"
WARNING unable to detect os for base image 'meyerj/unprivileged', maybe the base image does not exist But I also noticed a downside, namely if $ rocker meyerj/unprivileged
Building docker file with arguments: {'path': '/tmp/tmpgppwbqbt', 'rm': True, 'nocache': False, 'pull': False}
building > Step 1/2 : FROM meyerj/unprivileged
building > ---> 22d887b3ed36
building > Step 2/2 : USER root
building > ---> Using cache
building > ---> 5a200b7615ba
building > Successfully built 5a200b7615ba
Executing command:
docker run -it --rm 5a200b7615ba
root@a3fde251aeda:/# So I guess a potential follow-up could be to extend class |
* Fix using rocker for non-root containers If the base image given by the user does not have root privileges, building the rockerized image will fail. Extensions seem to expect that their Dockerfile snippets are executed with root privileges. This patch injects a `USER root` instruction right after FROM base_image. For similar reasons the `user` extension has to run last, because its snippet changes the active user again and subsequent snippets from other extensions might fail. * Revert redundant reordering of extensions * Fix user extension for some special cases - A user with the same UID already exists in the container image. - A group with the same GID already exists in the container image. - A user with the same name already exists in the container image. In all those cases the existing user or group gets deleted before creating a new one. Changing the password and adding the user to the sudo group is redundant to creating /etc/sudoers.d/rocker. * Suppress mail spool/home directory not found error output of userdel * tests: Remove obsolete check in UserExtensionTest * Revert "Suppress mail spool/home directory not found error output of userdel" This reverts commit c520a4e. * Create the parent directory of the home directory before calling mkhomedir_helper The tool fails with exit code 6 if the top-level directory does not exist yet. (a39bc32231c8)root@c71fe951b480:/# getent passwd johannes johannes:x:1000006:1000:Johannes Meyer:/share/homes/johannes:/bin/bash (a39bc32231c8)root@a39bc32231c8:/# rm share -R (a39bc32231c8)root@a39bc32231c8:/# mkhomedir_helper johannes; echo $? 6 (a39bc32231c8)root@a39bc32231c8:/# mkdir share (a39bc32231c8)root@a39bc32231c8:/# mkhomedir_helper johannes; echo $? 0
If the base image given by the user does not have root privileges, building the rockerized image will fail. Extensions seem to expect that their Dockerfile snippets are executed with root privileges.
This patch injects a
USER root
instruction right afterFROM base_image
. It is a no-op if the base image already runs as theroot
user.For similar reasons the
user
extension has to run last, because its snippet changes the active user again and subsequent snippets from other extensions might fail. But this is a special case only. Maybe the extension API should have a more general way to declare dependencies of extensions. For example,nvidia
depends onx11
. Without specifying both, I cannot run 3D-accelerated GUI applications in the rockerized container.