Nix shell to apptainer

How to create an apptainer image from a nix shell

Preface

Previously I have written about setting up nix to run on the University of Iowa’s compute cluster. At the time I noted some issues with this approach. These made the approach unusable long term and I needed another solution. The new solution I ended up adopting was building apptainer1 images from nix-shell definitions.

The Method

This is carried out in two steps. First we use dockerTools.buildNixShellImage to construct a docker image then convert this to an apptainer image.

The following example is from my own projects. I use npins and standalone shell.nix files. The same idea works with a flake, you just have to juggle the stuff around a bit. Here we create a new file container.nix:

{
  system ? builtins.currentSystem,
  pins ? import ./npins,
  pkgs ? import pins.nixpkgs { inherit system; },
}:
pkgs.dockerTools.buildNixShellImage {
  tag = "latest";
  drv = import ./shell.nix { };
  compressor = "none";
}

We then build the container with nix-build container.nix. Our docker image now lives in the nix store somewhere with the link result pointing to it. We can now convert this to apptainer:

apptainer \
  pull \
  container.sif \
  docker-archive://$(readlink result)

This approach does not spark joy, but it works and that’s what I needed right now.

Why didn’t you just —

I tried other stuff, it didn’t work.

Use nixpkgs singularity-tools?

They are currently scuffed. Not a great sign that there is an issue titled Beat singularity-tools up to shape

Build the apptainer image in nix?

apptainer really wants to talk to the internet, nothing I tried stopped it. As this is not kosher in the nix sandbox we build out of the sanbox. I’m not really sure why it feels the need to talk to the internet but oh well. I started exploring siftool as a potential way to convert without apptainer but turned back lest I get stuck in the rabbit hole.


  1. Also known as singularity containers↩︎