Reputation: 191749
I'm working on an macOS machine but I plan to run my executable on a Linux machine. I've found the jimmycuadra/rust Docker image which seems to suit my needs.
I do docker build .
with the following Dockerfile in the current directory.
FROM jimmycuadra/rust
ADD my_project /my_project
WORKDIR /my_project
RUN cargo build --release --target=x86_64-unknown-linux-gnu
This seems to build the project properly, but once Docker exits, there is no target
directory and there is no running container to docker cp
from either.
How can I get the Rust executable once it is built inside the Docker container?
Upvotes: 2
Views: 2124
Reputation: 892
You can directly run the images provided by the Rust development team on Docker Hub, and mount your source directory inside the image. You just need to be careful to also mount the directories that Cargo will use as cache, otherwise it will end up downloading packages and/or checking out source repositories for the dependencies with every new container run. Note that you should't bind-mount the entire /usr/local/cargo
directory, because this is where the official images put the binaries and other stuff.
Here's the little shell script that I put in my executable path as cargo
, and also symlinked as nightly-cargo
:
#!/bin/sh
if [ $(basename "$0") = nightly-cargo ]; then
rust_image=rustlang/rust:nightly
else
rust_image=rust:latest
fi
echo "Running cargo in $rust_image"
docker run -t --rm --user $(id -u):$(id -g) \
-v "$HOME"/.cargo/registry:/usr/local/cargo/registry \
-v "$HOME"/.cargo/git:/usr/local/cargo/git \
-v "$PWD":/mnt/crate --workdir /mnt/crate \
$rust_image cargo "$@"
Updated: I have set up an automatically rebuilt image repository which allows the user to bind-mount the entire /usr/local/cargo
. The caveat is that running rustup inside a container running one of these images with /usr/local/cargo
bind-mounted may produce surprising results.
Upvotes: 0
Reputation: 1494
I think you are overcomplicating things here by having a Dockerfile (I could be wrong if your needs are actually more complex than what you have shown, if so please provide further information and I will edit this answer). When you run ADD in the Dockerfile you are copying your code into the built image but you never copy the built object out again (and in fact there is no way I know to do that using a Dockerfile). There is no 'nice' way to get the resulting binary out of the image.
I think something simpler like this command will suit your needs better (run it after changing to the directory containing your code):
docker run -it -v "$(pwd):/source" jimmycuadra/rust cargo build --release --target=x86_64-unknown-linux-gnu
This mounts the current directory as /source
in the container (which is the default WORKDIR for the image you are using) and then builds your code, meaning the resulting executable will end up in the current folder:
ls target/x86_64-unknown-linux-gnu/release/
There is a slight problem with this - everything in the container runs as root and therefore the build artifacts get created with the owner set to the root user. This may cause issues for you trying to modify/remove them on your host later. To get around that you may be able to use something like this:
docker run -it -v "$(pwd):/source" jimmycuadra/rust sh -c "cargo build --release --target=x86_64-unknown-linux-gnu && chown -R $(id -u):$(id -g) ."
I say 'may' because I'm not sure if that will work on a Mac. I'm sure there is a way to achieve the same thing though.
Upvotes: 2