Developer nix-shell inside layered docker image

Hi Folks, I’d like to create a docker image that has an option to run a developer shell that matches a nix-shell environment. I tried doing something like this:

{ pkgs ? import <nixpkgs> { } }:
let
  buildInputs = [
    (pkgs.lib.getDev pkgs.openssl)
    (pkgs.lib.getLib pkgs.openssl)
  ];

  nativeBuildInputs = [
    pkgs.coreutils
    pkgs.gcc
    pkgs.gnumake
  ];
    
in {
  dockerImage = pkgs.dockerTools.buildLayeredImage {
    name = "test";
    tag = "latest";
    contents = buildInputs ++ nativeBuildInputs ++ [
      pkgs.bashInteractive
    ];
  };
}

If build build this image, and load it in podman, I get a very simple bash shell that lacks any of the NIX environment variables needed for gcc to find the openssl library and headers:

$ podman run --rm -it -v $HOME:$HOME -i test:latest /bin/bash
bash-5.1# env
HOSTNAME=d211c3ce7f82
PWD=/
container=podman
HOME=/
TERM=xterm
SHLVL=1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
_=/bin/env

Is there a way to do this?

1 Like

nix-shell does a lot more than just get some programs into PATH… it sets up environment variables and shell functions to do all sorts of things, runs hooks, and probably more I’m not thinking of.

If you want a nix-shell environment, the only realistic way to get it is to actually run nix-shell. So you would need the docker container to be capable of running nix, but at that point I question what the point is… why use docker for this?

why use docker for this?

Primarily because these Docker images are meant to run on a Docker-based Continuous Integration system.

It’s for a build process that primarily cross-builds some firmware, but also builts some native tools as part of the build process.

Ok… so if I want to pull in nix-shell, what’s the package I need for that?

Then let me reverse the question: why use nix-shell for this? If it’s not interactive, it seems like using nix derivations would be better.

pkgs.nix

Then let me reverse the question: why use nix-shell for this? If it’s not interactive, it seems like using nix derivations would be better.

If the build fails for some reason, it’s useful for developers to be able to pull the image down and run the build locally, so that can have the same process as the build machine uses - so the idea is to have a user-friendly shell as the default docker command.

I guess most people are just using dockerTools to deploy their software into Docker, rather than for this use case.

pkgs.nix

I don’t think that’s right - I don’t see any such package in nixpkgs.

$ nix repl
Welcome to Nix 2.8.1. Type :? for help.

nix-repl> pkgs = import <nixpkgs> {}

nix-repl> pkgs.nix
«derivation /nix/store/hxm0nv8pz851jil6x3ybgh1h1r84yvjk-nix-2.8.1.drv»

nix-repl> builtins.pathExists "${pkgs.nix}/bin/nix-shell"
true

I’m not sure how you’re looking, but it’s definitely there…

1 Like