docker volume masks parent folder in container?

Viewed 439

I'm trying to use a Docker container to build a project that uses rust; I'm trying to build as my user. I have a Dockerfile that installs rust in $HOME/.cargo, and then I'm trying to docker run the container, map the sources from $HOME/<some/subdirs/to/project> on the host in the same subfolder in the container. The Dockerfile looks like this:

FROM ubuntu:16.04

ARG RUST_VERSION

RUN \
export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
# install library dependencies
apt-get install [... a bunch of stuff ...] && \
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $RUST_VERSION && \
echo 'source $HOME/.cargo/env' >> $HOME/.bashrc && \
echo apt-get DONE

The build container is run something like this:

docker run -i -t -d --net host --privileged -v /mnt:/mnt -v /dev:/dev --volume /home/stefan/<path/to/project>:/home/stefan/<path/to/project>:rw --workdir /home/stefan/<path/to/project> --name <container-name> -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro -v /etc/shadow:/etc/shadow:ro -u 1000 <image-name>

And then I try to exec into it and run the build script, but it can't find rust or $HOME/.cargo:

docker exec -it <container-name> bash
$ ls ~/.cargo
ls: cannot access '/home/stefan/.cargo': No such file or directory

It looks like the /home/stefan/<path/to/project> volume is masking the contents of /home/stefan in the container. Is this expected? Is there a workaround possible to be able to map the source code from a folder under $HOME on the host, but keep $HOME from the container?

I'm un Ubuntu 18.04, docker 19.03.12, on x86-64.

2 Answers

Dockerfile read variable in physical machine. So you user don't have in virtual machine. Try change: $HOME to /root

echo 'source /root/.cargo/env' >> /root/.bashrc && \

I'll post this as an answer, since I seem to have figured it out.

When the Dockerfile is expanded, $HOME is /root, and the user is root. I couldn't find a way to reliably introduce my user in the build step / Dockerfile. I tried something like:

ARG BUILD_USER
ARG BUILD_GROUP

RUN mkdir /home/$BUILD_USER

ENV HOME=/home/$BUILD_USER

USER $BUILD_USER:$BUILD_GROUP
RUN \
echo "HOME is $HOME" && \
[...]

But didn't get very far, because inside the container, the user doesn't exist:

unable to find user stefan: no matching entries in passwd file

So what I ended up doing was to docker run as my user, and run the rust install from there - that is, from the script that does the actual build.

I also realized why writing to /home/$USER doesn't work - there is no /home/$USER in the container; mapping /etc/passwd and /etc/group in the container teaches it about the user, but does not create any directory. I could've mapped $HOME from the host, but then the container would control the rust versions on the host, and would not be that self contained. I also ended up needing to install rust in a non-standard location, since I don't have a writable $HOME in the container: I had to set CARGO_HOME and RUSTUP_HOME to do that.

Related