Rust on Fedora easily with Docker and HICA

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?

Problem statement

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 package? pip uninstall! A Docker image? Just docker rmi. New npm hotness? Simply npm remove. 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 CoreOS or 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 dnf, apt-get, pacman or 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 pip, 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 git.

Agenda

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.

HICA Labels

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.

Multirust builder

This image contains all three major Rust toolchains, namely stable, beta andnightly, 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

Derives from 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 io.hica.libraries:

LABEL io.hica.libraries='["rpm", "hif", "solv", "solvext", "repo", "rpmio", "hawkey", "glib-2", "gobject-2"]'  

Workflow

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 .
...

The 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 cargo build.

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.

Closing words

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.