NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
17.98k stars 13.99k forks source link

stack (haskell tool) docker fails on nixos #44120

Open guibou opened 6 years ago

guibou commented 6 years ago

Issue description

Any invocation of stack configured with docker will fail on nixos.

Stack mounts himself inside the container (using docker -v argument). However the container may not contains the necessary dependencies, especially the dynamic linker (which are stored in /nix/store). Hence it fails with a "classic" file not found error.

Steps to reproduce

nix-shell -p stack
# (now, in the nix-shell)
cd /tmp
stack new foo
cd foo
stack --docker --docker-image tweag/linear-types:0.1.9 --compiler ghc-8.5 build

This fails with:

Note: Enabling Nix integration, as it is required under NixOS
Received ExitFailure 1 when running
Raw command: /run/current-system/sw/bin/docker run -v /nix/store/13g0nrx8jx98fzp7nysvw3bscjgkymag-stack-1.7.1/bin/stack:/tmp/stack sha256:6c52f6d1e48298803bf79c70dd6f1fa28a3279efa3627739e7804f2d6e9d5ae7 /tmp/stack --version

Workaround

The failing command can be changed slightly to get a success:

/run/current-system/sw/bin/docker run -v /nix/store:/nix/store -v /nix/store/13g0nrx8jx98fzp7nysvw3bscjgkymag-stack-1.7.1/bin/stack:/tmp/stack sha256:6c52f6d1e48298803bf79c70dd6f1fa28a3279efa3627739e7804f2d6e9d5ae7 /tmp/stack --version

(Please note the -v /nix/store:/nix/store)

Having this change integrated in stack requires a patch, I was able to get nix-shell with a working stack using this:

with import <nixpkgs> {};

let
  patchFile = writeText "stack_fix.diff"
  ''diff --git a/src/Stack/Docker.hs b/src/Stack/Docker.hs
index d6601998..8101051e 100644
--- a/src/Stack/Docker.hs
+++ b/src/Stack/Docker.hs
@@ -151,6 +151,12 @@ reexecWithOptionalContainer mprojectRoot =
                                   [ "run"
                                   , "-v"
                                   , exePath ++ ":" ++ "/tmp/stack"
+                                  -- hack for nixos
+                                  -- the copied stack executable (see previous lines)
+                                  -- is using nix `ld` which is stored inside /nix/store
+                                  -- and is not available on the docker
+                                  , "-v"
+                                  , "/nix/store:/nix/store"
                                   , iiId imageInfo
                                   , "/tmp/stack"
                                   , "--version"]
'';

  patchedStack = stack.overrideAttrs(oldAttrs: { patches = [patchFile]; });

  wrappedStack = runCommand "wrap-stack" {}
    ''
    mkdir -p $out/bin
    echo '#!/usr/bin/env bash' > $out/bin/stack
    echo '${patchedStack}/bin/stack --docker-mount /nix/store:/nix/store "$@"' >> $out/bin/stack
    chmod u+x $out/bin/stack
    '';
in

mkShell {
   buildInputs = [  wrappedStack ];
}

In which there is two steps:

a) Patch stack. This patch will be used to mount /nix/store in the container when stack setup it (i.e. this fix the first failing command line) b) Wrap stack to add the --docker-mount option. This will be used to mount /nix/store in the container for any other stack command.

Note: using this nix file, then nix-shell and the initial example, I have a successful build.

Workaround discussion

Unfortunately, my solution is an adhoc hack: it won't work if the container already contains a /nix/store. I'm open to suggestions.

Technical details

 - system: `"x86_64-linux"`
 - host os: `Linux 4.18.0-rc4, NixOS, 18.09pre145679.dae9cf6106d (Jellyfish)`
 - multi-user?: `yes`
 - sandbox: `no`
 - version: `nix-env (Nix) 2.0.4`
 - channels(root): `"nixos-18.09pre145679.dae9cf6106d"`
 - channels(guillaume): `""`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`
thufschmitt commented 6 years ago

The workaround I generally use for that is to use --docker-stack-exe download which asks stack to re-install itself inside the container instead of mounting the host's stack

guibou commented 6 years ago

@regnat Thanks for the solution.

Do you think it may be a good idea to set this value by default on the stack provided in nixpkgs?

thufschmitt commented 6 years ago

Do you think it may be a good idea to set this value by default on the stack provided in nixpkgs?

@guibou That seems legit indeed, except that this must be done in such a way that it doesn't override whichever value is set in the stack.yaml since the option can take other values (so we can't do that by just wrapping the executable, but we probably have to patch the source to change the default)

stale[bot] commented 4 years ago

Thank you for your contributions.

This has been automatically marked as stale because it has had no activity for 180 days.

If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity.

Here are suggestions that might help resolve this more quickly:

  1. Search for maintainers and people that previously touched the related code and @ mention them in a comment.
  2. Ask on the NixOS Discourse.
  3. Ask on the #nixos channel on irc.freenode.net.