streamNixShellImage
pkgs.dockerTools.streamNixShellImage
Docs pulled from | This Revision | about 1 hour ago
Tests: nixos/tests/docker-tools-nix-shell.nix
Noogle detected
Implementation
The following is the current implementation of this function.
streamNixShellImage =
{
drv,
name ? drv.name + "-env",
tag ? null,
uid ? 1000,
gid ? 1000,
# Default to `/build` instead of a non-existent `/homeless-shelter` for backwards compatibility.
#
# https://github.com/NixOS/nix/issues/6379
homeDirectory ? "/build",
shell ? bashInteractive + "/bin/bash",
command ? null,
run ? null,
}:
assert lib.assertMsg (!(drv.drvAttrs.__structuredAttrs or false))
"streamNixShellImage: Does not work with the derivation ${drv.name} because it uses __structuredAttrs";
assert lib.assertMsg (
command == null || run == null
) "streamNixShellImage: Can't specify both command and run";
let
# A binary that calls the command to build the derivation
builder = writeShellScriptBin "buildDerivation" ''
exec ${lib.escapeShellArg (valueToString drv.drvAttrs.builder)} ${lib.escapeShellArgs (map valueToString drv.drvAttrs.args)}
'';
staticPath = "${dirOf shell}:${lib.makeBinPath [ builder ]}";
# https://github.com/NixOS/nix/blob/2.32.0/src/nix/nix-build/nix-build.cc#L617-L651
rcfile = writeText "nix-shell-rc" ''
unset PATH
dontAddDisableDepTrack=1
# TODO: https://github.com/NixOS/nix/blob/2.32.0/src/nix/nix-build/nix-build.cc#L628
[ -e $stdenv/setup ] && source $stdenv/setup
PATH=${staticPath}:"$PATH"
SHELL=${lib.escapeShellArg shell}
BASH=${lib.escapeShellArg shell}
set +e
[ -n "$PS1" -a -z "$NIX_SHELL_PRESERVE_PROMPT" ] && PS1='\n\[\033[1;32m\][nix-shell:\w]\$\[\033[0m\] '
if [ "$(type -t runHook)" = function ]; then
runHook shellHook
fi
unset NIX_ENFORCE_PURITY
shopt -u nullglob
shopt -s execfail
${optionalString (command != null || run != null) ''
${optionalString (command != null) command}
${optionalString (run != null) run}
exit
''}
'';
# https://github.com/NixOS/nix/blob/2.32.0/src/libstore/include/nix/store/globals.hh#L778-L788
sandboxBuildDir = "/build";
drvEnv =
devShellTools.unstructuredDerivationInputEnv { inherit (drv) drvAttrs; }
// devShellTools.derivationOutputEnv {
outputList = drv.outputs;
outputMap = drv;
};
# Environment variables set in the image
envVars = {
# Root certificates for internet access
SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
NIX_SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
# https://github.com/NixOS/nix/blob/2.32.0/src/libstore/unix/build/derivation-builder.cc#L1001-L1004
# PATH = "/path-not-set";
# Allows calling bash and `buildDerivation` as the Cmd
PATH = staticPath;
# https://github.com/NixOS/nix/blob/2.32.0/src/libstore/unix/build/derivation-builder.cc#L1006-L1012
HOME = homeDirectory;
# https://github.com/NixOS/nix/blob/2.32.0/src/libstore/unix/build/derivation-builder.cc#L1014-L1018
NIX_STORE = storeDir;
# https://github.com/NixOS/nix/blob/2.32.0/src/libstore/unix/build/derivation-builder.cc#L1020-L1021
# TODO: Make configurable?
NIX_BUILD_CORES = "1";
}
// drvEnv
// {
# https://github.com/NixOS/nix/blob/2.32.0/src/libstore/unix/build/derivation-builder.cc#L1035-L1037
NIX_BUILD_TOP = sandboxBuildDir;
# https://github.com/NixOS/nix/blob/2.32.0/src/libstore/unix/build/derivation-builder.cc#L1039-L1040
TMPDIR = sandboxBuildDir;
TEMPDIR = sandboxBuildDir;
TMP = sandboxBuildDir;
TEMP = sandboxBuildDir;
# https://github.com/NixOS/nix/blob/2.32.0/src/libstore/unix/build/derivation-builder.cc#L1042-L1046
PWD = sandboxBuildDir;
# https://github.com/NixOS/nix/blob/2.32.0/src/libstore/unix/build/derivation-builder.cc#L1079-L1082
# We don't set it here because the output here isn't handled in any special way
# NIX_LOG_FD = "2";
# https://github.com/NixOS/nix/blob/2.32.0/src/libstore/unix/build/derivation-builder.cc#L1084-L1085
TERM = "xterm-256color";
};
in
streamLayeredImage {
inherit name tag;
contents = [
binSh
usrBinEnv
(fakeNss.override {
# Allows programs to look up the build user's home directory.
#
# https://github.com/NixOS/nix/blob/2.32.0/src/libstore/unix/build/linux-derivation-builder.cc#L409-L416
#
# This slightly differs, however, since we use the passed-in `homeDirectory` instead of `sandboxBuildDir`.
# We're doing this because it is arguably a bug in Nix that `sandboxBuildDir` is used here.
#
# https://github.com/NixOS/nix/issues/6379
extraPasswdLines = [
"nixbld:x:${toString uid}:${toString gid}:Build user:${homeDirectory}:/noshell"
];
extraGroupLines = [
"nixbld:!:${toString gid}:"
];
})
];
fakeRootCommands = ''
# Effectively a single-user installation of Nix, giving the user full
# control over the Nix store. Needed for building the derivation this
# shell is for, but also in case one wants to use Nix inside the image.
mkdir -p ./nix/{store,var/nix} ./etc/nix
chown -R ${toString uid}:${toString gid} ./nix ./etc/nix
# Gives the user control over the build directory.
mkdir -p .${sandboxBuildDir}
chown -R ${toString uid}:${toString gid} .${sandboxBuildDir}
'';
# Run this image as the given uid/gid
config.User = "${toString uid}:${toString gid}";
config.Cmd =
# https://github.com/NixOS/nix/blob/2.32.0/src/nix/nix-build/nix-build.cc#L240-L241
# https://github.com/NixOS/nix/blob/2.32.0/src/nix/nix-build/nix-build.cc#L659
if run == null then
[
shell
"--rcfile"
rcfile
]
else
[
shell
rcfile
];
config.WorkingDir = sandboxBuildDir;
config.Env = lib.mapAttrsToList (name: value: "${name}=${value}") envVars;
};