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

Support for building as root user #96

Closed
TilBlechschmidt opened this issue Aug 5, 2020 · 8 comments
Closed

Support for building as root user #96

TilBlechschmidt opened this issue Aug 5, 2020 · 8 comments
Assignees

Comments

@TilBlechschmidt
Copy link

How could this project be improved?
In some scenarios it might be preferred to build the project as the root user instead of the lower privilege rust user. One such example would be GitHub Actions. The Docker image is executed in an ephemeral VM whose only purpose is to run the build and die. Using this image in its current state requires a lot of permission changes prior and post build especially when using the cache action.

If you're interested in implementing this feature yourself, how could I help you?
I have made a very crude "fix" to the image in my fork which is used by this script run by this Action. Although this works it is rather hacky. A proper solution would probably be either a global installation of the toolchain in the image or a separate tag for a root-based image.

If you would be willing to accept such a change, I could spend some time in the next few weeks to sketch a PR for this.

@emk
Copy link
Owner

emk commented Sep 4, 2020

If you create a Dockerfile that includes FROM ekidd/rust-musl-builder, you should be able to just use USER root to change the default user back to root. (For dubious reasons going back many years, I believe we also have sudo installed and configured.)

I would love to support GitHub Actions better, because I'm slowing migrating my own projects over to it. But at the same time, I would strongly prefer to minimize any breakage of existing CI setups that use ekidd/rust-musl-builder. I'm definitely thinking about how to handle this, but I think I need to migrate a few more projects first.

@E-gy
Copy link

E-gy commented Sep 4, 2020

you should be able to just use USER root

well yes, but actually no[t quite] - rustup installs toolchains per user (see rust-lang/rustup#313)

in the image, the toolchain is installed for the rust user and only.

RUN rustup toolchain list
USER root
RUN rustup toolchain list

Step 1/4 : FROM ekidd/rust-musl-builder:latest as builder
 ---> ccd27aadcb92
Step 2/4 : RUN rustup toolchain list
 ---> Running in 83f8b4c9d57a
stable-x86_64-unknown-linux-gnu (default)
Removing intermediate container 83f8b4c9d57a
 ---> dccb4bd19257
Step 3/4 : USER root
 ---> Running in 6b14bd949f89
Removing intermediate container 6b14bd949f89
 ---> 2445c13a1190
Step 4/4 : RUN rustup toolchain list
 ---> Running in 0dfc4833ccf7
no installed toolchains

resp. Running rustup default stable (as root) redownloads the entire toolchain.

emk added a commit that referenced this issue Sep 6, 2020
This PR attempts to lay the groundwork to address
#96. In particular, we
install the Rust toolchain globally by abusing `rustup`.

We still preserve the legacy `rust` user but we now encourage derived
Dockerfiles to consider `USER root`.

This PR also removes ARM support. We want to explore the idea of
supporting ARM more reliably using a separate image, but perhaps it
would be better to refer those users to one of the Rust
cross-compilation toolchains. See
#63 for discussion.
@emk
Copy link
Owner

emk commented Sep 6, 2020

I have opened PR #100, which tries make USER root work by installing a global toolchain using the approach described at rust-lang/rustup#2383. I've kicked off a build of this as ekidd/rust-musl-builder:experimental-stable.

I'm reluctant to actually make root the default user, because that might break a fair number of existing users. But this should at least get us a lot closer, and make it easier to build a custom image that uses FROM ekidd/rust-musl-builder:experimental-stable and USER root to work better with GitHub Actions.

I'm actually planning to work on a GitHub-based build on Monday and I make have some new ideas then. But I'm also very interested in feedback. Please let me know if you have any other ideas about how to approach this.

gibfahn added a commit to gibfahn/rust-musl-builder that referenced this issue Oct 27, 2020
This is the minimal change needed to allow the docker image to be run
with `--user root` and still build correctly.

There may be better long-term ways of doing this, but hopefully this is
small enough to be uncontroversial.

This isn't a breaking change for users running normally (as the `rust`
user) because these are already the default paths.

Refs: emk#96
Refs: emk#100
@gibfahn
Copy link

gibfahn commented Oct 27, 2020

Got running as root working (for similar CI needs) by setting RUSTUP_HOME and CARGO_HOME appropriately, with no other changes.

i.e. adding -e CARGO_HOME=/home/rust/.cargo -e RUSTUP_HOME=/home/rust/.rustup to my docker run args. Maybe just setting these vars in the default image might be good enough for now, raised #105 for that purpose.

@mverleg
Copy link

mverleg commented Nov 22, 2020

I would also be happy if I wouldn't need to fiddle with file permissions. I can't think of a backwards-compatible way to change it though.

Beyond the COPY --chown=rust things, for reasons I'm not sure about, some build steps work locally but not on Github Actions. (userid difference maybe?). E.g. WORKDIR /app followed by RUN mkdir ./src works locally but fails on Github for me.

Based on @gibfahn's comment I used a Dockerfile starting with

FROM ekidd/rust-musl-builder:1.48.0 AS build
ENV CARGO_HOME=/home/rust/.cargo
ENV RUSTUP_HOME=/home/rust/.rustup
USER root

and that seems to work. Of course it's not super elegant, but maybe useful for some.

@emk
Copy link
Owner

emk commented Jan 5, 2021

This should now be officially supported in the new 1.49.0 release! (I wanted to roll this out with a new Rust release so that anybody whose CI system breaks will still have to option of using 1.48.0, rather than replacing the existing 1.48.0 release.)

You still need to do something like:

ENV CARGO_HOME=/home/rust/.cargo RUSTUP_HOME=/home/rust/.rustup
USER root

...but this should now work. See the CHANGELOG.md file for notes. Thank you to everyone who pointed this out!

We may eventually come up with a better system, but this is the current compromise to avoid breaking too many people's CI.

@emk emk closed this as completed Jan 5, 2021
@gibfahn
Copy link

gibfahn commented Jan 5, 2021

@emk any thoughts on merging #105 to fix needing to set the env vars?

@gibfahn
Copy link

gibfahn commented Jan 8, 2021

@emk Replying to #105 (comment)

I have merged a slightly different version of this idea. Please let me know if it works for you (assuming you're still using it)!

So it looks like you changed these from:

CARGO_HOME=/home/rust/.cargo
RUSTUP_HOME=/home/rust/.rustup

to

CARGO_HOME=/opt/rust/cargo
RUSTUP_HOME=/opt/rust/rustup

right?

Now RUSTUP_HOME is set in the docker env, so the fix is to not set RUSTUP_HOME, and leave CARGO_HOME to the default, which is /home/rust/.cargo for the default user, and /root/.cargo for root.

That breaks my existing scripts (e.g. this) as they're now setting RUSTUP_HOME to the old value, but that's not a big deal as this was already a not-really-supported configuration, and it's an easy fix.


The bigger issue (for me) is that this makes caching harder. My existing solution is to add these lines to my docker run:

    -v "${XDG_CACHE_HOME:-$HOME/.cache}"/docker/cargo/registry:/home/rust/.cargo/registry \
    -v "${XDG_CACHE_HOME:-$HOME/.cache}"/docker/cargo/git:/home/rust/.cargo/git           \

This caches the registry and git cargo caches (see Cargo caching docs), and makes running this image almost as fast as running locally. However now I have to change this based on whether the user is running as root or rust, as their CARGO_HOME will change. It's also not easy to work out what the value of $HOME will be in the container before running it. If I want to cache the bin directory too this is now more complex as that is at /opt/rust/cargo/bin (and I'm not sure if another one will be created at ~/.cargo/bin):

rust@ea12b164a783:~/.cargo$ ls ~/.cargo; ls /opt/rust/cargo
config  git  registry
bin  config  env

Looking at rust-lang/rustup#2383 (linked to from 3ae8179#diff-dd2c0eb6ea5cfc6c4bd4eac30934e2d5746747af48fef6da689e85b752f39557), it looks like the reason they suggest not setting CARGO_HOME is to allow multiple users on a shared machine to run at the same time. The second comment on that issue suggests that that's a bad idea, and in any case there's not much reason to do so in a docker container anyway. Having a consistent CARGO_HOME would make things simpler too. You'd have to ensure the rust user can access the directory of course.

I'm unsure if there's something else I'm missing that makes using CARGO_HOME=/opt/rust/cargo problematic. For now I can simply start to set --env CARGO_HOME=/opt/rust/cargo in my docker run command instead of the previous locations.

gibfahn added a commit to gibfahn/up-rs that referenced this issue Jan 8, 2021
Removing `RUSTUP_HOME` makes `cargo build` work again, and the other
changes fix up caching.

Refs: emk/rust-musl-builder#96 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants