This is a companion post to building Python docker deployment images using pyenv and poetry. Where in that post the image is built using standard Python tooling, in this post the images are built using the fully declarative, reproducible NIX system.

The advantage of this approach is full control of the software supply chain, easy ways to create highly optimised machine code, and hooks to modify any of the software sources as needed before compilation.

The build is straightforward:

  1. NiX has built-in support for building docker-compatible images using dockerTools.buildImage function
  2. The Python and needed packages environment is defined using the python3.withPackages function

This is all! A fully declarative image is built which can easily be modified with custom compilation options, patches etc. Here is the full NiX file:

let
  pkgs = (import <nixpkgs>) { } ;
  scienv = pkgs.python3.withPackages(ps: with ps; [ numpy scipy] );  
in
rec {
jax = pkgs.dockerTools.buildImage {
    name = "scipy";
    tag = "latest";
    copyToRoot = pkgs.buildEnv {
      name = "image-root";
      paths = with pkgs; [
        coreutils
        bashInteractive
        scienv
      ];
      pathsToLink = [ "/bin" ];
    };
};
}