How to access rust and cargo as a none root user in Docker

Hello everyone,

I’ve encountered a persistent issue when trying to access the Rust toolchain (rustc and cargo ) from within a Docker container, specifically when operating as a non-root user. Despite several attempts and strategies, I consistently face errors related to the Rust toolchain not being accessible or rustup related errors when trying to run rustc --version or cargo --version

I'm trying to build my application and use it for my github actions which i have set up on github.

Environment and Setup:

  • Base Image: I start with a rust:1.75.0 image to build my Rust application and then move to an ubuntu base image for the final setup.
  • Dockerfile Approach:
    • In the rust:1.75.0 image, I successfully compile my application and install necessary dependencies.
    • I then copy the compiled binary and Rust toolchain binaries (/usr/local/cargo/bin/*) to /usr/local/bin/ in the ubuntu image.
    • A non-root user (userGeo) is created, and I switch to this user before running any commands.
    • Despite setting PATH appropriately and ensuring permissions, I cannot access rustc or cargo as userGeo.
    • As a root user i can only access cargo and rustc in the first image build, but when copied to my ubuntu image i no longer have access. the below error is all i get in all situations as none root user and a root user in the final image build which is ubuntu

no rustup userGeo@47******b:/usr/local/bin$ rustc --version
error: rustup could not choose a version of rustc to run, because one wasn't specified explicitly, and no default is configured.
help: run 'rustup default stable' to download the latest stable release of Rust and set it as your default toolchain.

WORKDIR /src
COPY . .
RUN cargo build --locked --workspace

# Install sqlx-cli for database operations
RUN cargo install sqlx-cli --no-default-features --features native-tls,postgres

FROM ubuntu
# Update and install necessary packages including OpenSSL which sqlx-cli needs
RUN apt-get update && apt-get install -y libssl-dev pkg-config ca-certificates make curl build-essential && rm -rf /var/lib/apt/lists/*

# Create a new user 'userGeo' and group 'rustgroup'
RUN groupadd rustgroup && useradd -m -g rustgroup userGeo

# Set the HOME environment variable for userGeo
WORKDIR /home/userGeo

# Copy the sqlx-cli binary from the build stage
COPY --from=build /usr/local/cargo/bin/sqlx /usr/local/bin/sqlx

# Copy the rust toolchain from the build stage
COPY --from=build /usr/local/cargo/bin/* /usr/local/bin/

# Copy the compiled binary from the build stage to /usr/local/bin
COPY --from=build /src/target/debug/psp /usr/local/bin/psp

# Ensure 'userGeo' has the necessary permissions over their directories
RUN chown -R userGeo:rustgroup /home/userGeo

# Copy the entire /src directory to the working directory of userGeo in the Ubuntu image
COPY --from=build /src /home/userGeo

# Set the permissions so all users can execute the Rust binaries and give usergeo  permissions
RUN chmod -R 755 /usr/local/bin/

# Switch to the non-root user for running the application
USER userGeo

CMD ["PSP"]```

above is my docker file. maybe i am doing it wrong.  i have scanned through the web and i haven't been able to resolve this, any help would be super helpful

this is not enough, the binaries in $CARGO_HOME/bin are just shims that will eventually invoke the real toolchain at $RUSTUP_HOME/toolchains/$your-default-toolchain-triplet/bin/

but even if you copy all the toolchain binaries, it's still not enough, the tools still need access to other components like the libraries.

if you need the rust toolchains, you either need to copy the whole $RUSTUP_HOME and $CARGO_HOME directories, (and don't forget to set the environment variables accordingly), or you should just re-install rustup and the toolchain directly.

btw, you DO NOT need to be root to install rustup and toolchains.

what I don't understand is that, since you need the rust toolchains anyway, what's the point to copy the files to a second image? could you explain the motivation -- what are you really trying to achieve, please? if you are asking the wrong questions, you'll only get useless answers, which is a waste of time for everyone.

1 Like

a single image would be too big for my use case, so a multi-stage build would drastically reduce the image size, two, my CI/CD on Github actions run on Ubuntu hence, and three, I want to separate the build build environment from the runtime environment.

its not about been the root or none root user sir, i just don't have access to them when in the final image, it gives the rustup unable to choose a version of rustc to run. it only works in the first image build. i need the rust and cargo in my final image because my application needs it to run.

hello,

I was able to fix the issue following your approach. I had to manually install rustup in the final image instead of trying to copy it. and ensuring that the user group i created owns the copied files from the first image. i also had to ensure that i set the path, because rustup is only effective in new sessions, the work around was me me manually adding the cargo bin directory to the path.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.