DEV Community

Ingun 전인건
Ingun 전인건

Posted on

Azure Function app that runs Haskell Nix package

I built a containerized Azure Function App that internlly runs a haskell program packaged with Nix.

I followed Create your first containerized functions on Azure Container Apps to make a scaffold. Runtime could be anything than can run sub process, which is everything. So I choose dotnet.

And at the end of the generated Dockerfile, I added some nix layers.

# Basic runtime to install nix RUN apt install -y xz-utils curl RUN bash -c "sh <(curl -L https://nixos.org/nix/install) --daemon --yes" # Update PATH to include nix tools ENV PATH="/home/.nix-profile/bin:/nix/var/nix/profiles/default/bin:${PATH}" 
Enter fullscreen mode Exit fullscreen mode

Then I copied my haskell project.

ADD haskell-project /opt/haskell-project 
Enter fullscreen mode Exit fullscreen mode

Create haskell package using cabal2nix. I call nix-collect-garbage to reduce the size of docker layer.

RUN nix-shell -p cabal2nix --run 'cabal2nix --no-check /opt/haskell-project > /opt/haskell-project/foo.nix' && nix-collect-garbage 
Enter fullscreen mode Exit fullscreen mode

The default.nix would look like this. It calls the haskell package and wrap it with justStaticExecutables to leave only runtime dependencies.

let p = (import <nixpkgs> {}).pkgs; in p.haskell.lib.compose.justStaticExecutables (p.haskellPackages.callPackage ./foo.nix {}) 
Enter fullscreen mode Exit fullscreen mode

Build the nix package

RUN nix-build 
Enter fullscreen mode Exit fullscreen mode

In the Function implementation, run the hasell executable as a subprocess

using System.Diagnostics; using (Process hs = new Process()) { hs.StartInfo.UseShellExecute = true; hs.StartInfo.FileName = "/opt/haskell-project/result/bin/exe"; hs.Start(); await hs.WaitForExitAsync(); if (hs.ExitCode != 0) { throw new Exception($"haskell subprocess failed {hs.ExitCode}"); } } 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)