nixDatabase contains paths which are not part of the image
kolloch opened this issue · 3 comments
In nixDatabase = makeNixDatabase ([configFile] ++ copyToRootList ++ layers);
store paths are added to the nixDatabase which are actually not in the image itself -- i.e. the image configurations.
That leads to errors when the resulting image is used to build itself again. The database will claim that the config is already in the store but then it cannot be opened.
This is because the configuration file path is explicitly ignored to avoid building a new layer when a configuration parameter is updated. We need to take the configuration file into account in order to create a layer with its closure but we don't need to put the configuration into a layer since this configuration file already part of the OCI image itself.
So, I htink we would have two options:
- improve
makeNixDatabase
to ignore the configuration file path (better but harder) - add the configuration file into the layer when the
initializeNixDatabase=true
(more simple but not really nice :/)
Even though the config files are tiny, I also like the first approach more.
So I guess it is about filtering the storepaths specified in the ignore
setting of the layers? Is an "ignored" path only ignored in the same layer or globally? => checked: per layer
I think only in the same layer would work as expected but would also be so much more complicated: Then we would need to calculate the closure of each layer and subtract the ignore path(s) and then create the union.
The nix2container binary has an option to explicitly ignore a path when building the tar of the layer. We then provide the path of the config file.
So, we don't have to fix anything regarding the layers construction.
However, the configuration file path is not ignored when the Nix database is built. To build this database, we use the pkgs.closureInfo
function which generates a file containing all store paths of the closure. I don't remember how this file looks like, but to fix this issue, we would have to modify this file by excluding the path of the configuration file.
Since the configuration file is not a dependency of another store path, we could exclude it without breaking the closure graph.
So, in pseudo code, i think it would look like:
- makeNixDatabase = paths: pkgs.runCommand "nix-database" {} ''
+ makeNixDatabase = configurationFilePath: paths: pkgs.runCommand "nix-database" {} ''
mkdir $out
echo "Generating the nix database..."
export NIX_REMOTE=local?root=$out
# A user is required by nix
# https://github.com/NixOS/nix/blob/9348f9291e5d9e4ba3c4347ea1b235640f54fd79/src/libutil/util.cc#L478
export USER=nobody
- ${pkgs.nix}/bin/nix-store --load-db < ${pkgs.closureInfo {rootPaths = paths;}}/registration
+ registration=${pkgs.closureInfo {rootPaths = paths;}}/registration
+ filtered_registration=$(something-to-remove-path-in-the-registration-file ${configurationFilePath} registration)
+ ${pkgs.nix}/bin/nix-store --load-db < filtered_registration
mkdir -p $out/nix/var/nix/gcroots/docker/
for i in ${l.concatStringsSep " " paths}; do
(i don't have time atm to dig more :()