Rust in Fedora has serious bootstrapping issues and given the nature of beta/nightly releases channels it doesn't even seem like an advantageous candidate for downstream packaging. On the other hand, maintaining all the customary upstream installers and package formats is a problem on its own. So let's contain all the stuff in Docker containers and wire them back to the host with HICA, shall we?
I have my little application written in Rust that I want to compile with various versions of Rust, on a whim. With projects like
multirust it's actually very easy to do that, except for the times when it isn't. Don't get me wrong, this isn't based on some bad experience with
multirust or Rust in general, just something I've been burned by in the past, and the problem is actually much more general than a single language or toolchain.
So what is the problem? Too many answers to the same question - how do I get rid of X? An RPM package? Sure do
dnf remove. A
pip uninstall! A Docker image? Just
docker rmi. New
npm hotness? Simply
curl | bash install script? Oh well. Sometimes crap I haven't used for months or years somehow keeps sitting on my hard disk because it's so damn hard to dispose of properly.
Unless you're a hipster using the new immutable OS's like
Atomic then, apart from being really intricate with all those
docker this and
docker that invocations, you're also gonna need an intricate knowledge of your package manager like
nix. But let's say for now that package managers are an inherent burden of using any Linux distribution in general, so let's focus for a moment on the
docker part. In the light of the paragraph above,
docker makes it really easy to simply hit it and leave it. Like without all the complexity, no more
npm this or that, just remove the image and you're done. All you need is this recipe called
Dockerfile which is a text file that you can keep track of using
We're going to create two HICA applications, first a base (multi)Rust builder, the second a specialized image for the particular project. The images are going to be annotated with HICA labels for additional functionality, so let's take a quick detour into that particular area.
Containers need a lot of care to work really seamlessly. And by seamlessly I mean that you simply don't neither know nor care whether the command you're invoking is actually run in a container. Images can be, at the Dockerfile level, annotated with functional labels that make some additional stuff happen when the container is spun off. Bind mounts from host for paths, devices, X11 or tty allocations can all be controlled via a very simple system of labels. For more comprehensive summary please refer here.
This image contains all three major Rust toolchains, namely
nightly, managed via multirust as well as all the distribution packages necessary for it to work. To make the integration with host smooth, these HICA labels are defined:
io.hica.bind_pwd to bind mount current working directory,
io.hica.tty to get proper input / output and finally
io.hica.command_aliases to define some shortcuts.
Fedora 22, 23 and rawhide Dockerfiles can be found here.
Application container based on Rust
multirust builder and contains actually only a single additional thing, the set of libraries to bind mount from host into the builder container defined as HICA label
LABEL io.hica.libraries='["rpm", "hif", "solv", "solvext", "repo", "rpmio", "hawkey", "glib-2", "gobject-2"]'
I have a source code in a directory on host and want to compile & link from my multirust container. First we need to build the images:
$ git clone https://github.com/shaded-enmity/fedora-rust $ git clone https://github.com/shaded-enmity/feaders-rs $ ls fedora-rust feaders-rs $ cd fedora-rust $ docker build -f Dockerfile.22 -t fedora-rust . ... $ cd ../feaders-rs $ docker build -t feaders . ...
Dockerfile.22 variant was not chosen at random, I'm running F22 on the host.
With the images built let's compile the project:
$ hica feaders build-stable $ target/debug/feaders --version feaders - 0.2.0
build-stable is a HICA command alias for
multirust run stable cargo build, which simply selects the Rust stable toolchain and issues a
And yes, everything just works, current working directory is bind mounted and
cd'd into, necessary libraries are found on host in
/usr/lib64 and bind mounted into the container and that's all that's needed. The
--verbose option of HICA can reveal the final unholy incantation:
$ hica --verbose feaders build-stable docker run -i -u 1000:1000 --security-opt label:disable --volume=/usr/lib64/libglib-2.0.so.0.4400.1:/usr/lib64/libglib-2.0.so --volume=/usr/lib64/libgobject-2.0.so.0.4400.1:/usr/lib64/libgobject-2.0.so --volume=/usr/lib64/libhawkey.so.2:/usr/lib64/libhawkey.so --volume=/usr/lib64/libhif.so.1.0.7:/usr/lib64/libhif.so --volume=/usr/lib64/librepo.so.0:/usr/lib64/librepo.so --volume=/usr/lib64/librpm.so.3.3.1:/usr/lib64/librpm.so --volume=/usr/lib64/librpmio.so.3.3.1:/usr/lib64/librpmio.so --volume=/usr/lib64/libsolv.so.0:/usr/lib64/libsolv.so --volume=/usr/lib64/libsolvext.so.0:/usr/lib64/libsolvext.so --volume /home/po/Repos/feaders-rs:/home/po/Repos/feaders-rs -w /home/po/Repos/feaders-rs -t feaders multirust run nightly cargo build
That can't possibly be secure
Right, it isn't - running the stuff directly on host wouldn't be secure either. Containers are used because:
1) They're easy to create and delete
2) They nicely shield you away from Murphy, much less against Machiavelli indeed
Apart from that containers are by default run as UID of the invoking user, so DAC restrictions still apply. HICA will not download any images, so you have to download/build using Docker directly.
When you're done with Feaders or Rust, simply
docker rmi -f feaders fedora-rust and everything will be gone. No need to worry about which installer put what and where - it's all contained. Be sure to check out other cool HICA images in the examples directory.