Posted on September 18, 2016
Tags: nerd, haskell, docker, nix

I previously wrote about using Nix pkgs.dockerTools being a handy way of making docker images.

Unfortunately, sometimes it’s too strict about dependencies, and you end up with way too much in the image. Also sometimes you want to chop and change the image contents in an impure way.

There is another way of building docker images, which still lets you take advantage of nix-build and its caching, but is more relaxed about the build process.

Basically, you use Nix to build a shell script. The shell script, when run, copies what it needs out of the Nix store into a temporary directory. It creates a minimal Dockerfile in the same directory, then builds it with docker.

So to execute your build, you would do:

nix-build && ./result

Here is such a build script which I wrote: hoogle-local/default.nix. It’s not pretty, but quite effective at making a minimal image which rebuilds fast.

This particular image is a handy thing John Wiegley started. It’s a docker image which runs a local Hoogle server loaded with a useful set of packages.

NixOS already has the facility for running a local Hoogle server. For example:

# configuration.nix
{ config, lib, pkgs, ... }:
{
  services.hoogle.enable = true;
  services.hoogle.port = 8686;
  services.hoogle.packages = hp: with hp; [
    conduit
    scotty
    wai
    # ... and so on ...
  ];
}

However, enabling the NixOS module with a large number of packages slows down channel upgrades. Also, if there is a build failure in any one of the Haskell packages (such breakages can happen with new version combinations), then you can’t upgrade. For these reasons, I prefer to use the above Docker image to decouple building the large set of packages from upgrading my system.