dockerTools.buildImageWithNixDb: populate the Nix Db of the image Nix store

Currently, the contents closure is copied to the layer but there is no
nix database initialization. If pkgs.nix is added in the contents,
nix-store doesn't work because there is no nix database.

From the contents of the layer, this commit generates and loads the
database in the nix store of the container. This only works if there
is no parent layer that already have a nix store (to support several
nix layers, we would have to merge nix databases of parent layers).

We also add an example to play with the nix store inside the
container. Note it seems `more` is a missing dependency of the nix
package!
This commit is contained in:
Antoine Eiche 2017-08-25 11:47:28 +02:00
parent 2c2cd34b54
commit df589a438e
2 changed files with 46 additions and 3 deletions

View file

@ -10,6 +10,8 @@
lib,
pkgs,
pigz,
nixUnstable,
perl,
runCommand,
rsync,
shadow,
@ -27,7 +29,7 @@
rec {
examples = import ./examples.nix {
inherit pkgs buildImage pullImage shadowSetup;
inherit pkgs buildImage pullImage shadowSetup buildImageWithNixDb;
};
pullImage =
@ -239,6 +241,17 @@ rec {
${text}
'';
nixRegistration = contents: runCommand "nix-registration" {
buildInputs = [ nixUnstable perl ];
# For obtaining the closure of `contents'.
exportReferencesGraph =
let contentsList = if builtins.isList contents then contents else [ contents ];
in map (x: [("closure-" + baseNameOf x) x]) contentsList;
}
''
printRegistration=1 perl ${pkgs.pathsFromGraph} closure-* > $out
'';
# Create a "layer" (set of files).
mkPureLayer = {
# Name of the layer
@ -544,4 +557,21 @@ rec {
in
result;
# Build an image and populate its nix database with the provided
# contents. The main purpose is to be able to use nix commands in
# the container.
# Be careful since this doesn't work well with multilayer.
buildImageWithNixDb = args@{ contents ? null, extraCommands ? "", ... }:
buildImage (args // {
extraCommands = ''
echo "Generating the nix database..."
echo "Warning: only the database of the deepest Nix layer is loaded."
echo " If you want to use nix commands in the container, it would"
echo " be better to only have one layer that contains a nix store."
# This requires Nix 1.12 or higher
export NIX_REMOTE=local?root=$PWD
${nixUnstable}/bin/nix-store --load-db < ${nixRegistration contents}
'' + extraCommands;
});
}

View file

@ -7,7 +7,7 @@
# $ nix-build '<nixpkgs>' -A dockerTools.examples.redis
# $ docker load < result
{ pkgs, buildImage, pullImage, shadowSetup }:
{ pkgs, buildImage, pullImage, shadowSetup, buildImageWithNixDb }:
rec {
# 1. basic example
@ -83,7 +83,7 @@ rec {
};
# 4. example of pulling an image. could be used as a base for other images
nix = pullImage {
nixFromDockerHub = pullImage {
imageName = "nixos/nix";
imageTag = "1.11";
# this hash will need change if the tag is updated at docker hub
@ -101,4 +101,17 @@ rec {
pkgs.nano
];
};
# 5. nix example to play with the container nix store
# docker run -it --rm nix nix-store -qR $(nix-build '<nixpkgs>' -A nix)
nix = buildImageWithNixDb {
name = "nix";
contents = [
# nix-store -qR uses the 'more' program which is not included in
# the pkgs.nix dependencies. We then have to manually get it
# from the 'eject' package:/
pkgs.eject
pkgs.nix
];
};
}