Use image.includeStorePaths = false, no more "arion base image"

The arion base image was a poor substitute for the customization
layer that only worked for some images.

By modifying dockerTools to export only the customization layer,
we can support arbitrary root contents.
This commit is contained in:
Robert Hensing 2021-05-25 19:25:15 +02:00
parent ad41d1e39b
commit 48d3d4b0d7
4 changed files with 45 additions and 48 deletions

View file

@ -3,6 +3,5 @@
./modules/composition/host-environment.nix ./modules/composition/host-environment.nix
./modules/composition/images.nix ./modules/composition/images.nix
./modules/composition/service-info.nix ./modules/composition/service-info.nix
./modules/composition/arion-base-image.nix
./modules/composition/composition.nix ./modules/composition/composition.nix
] ]

View file

@ -1,40 +0,0 @@
# This module is subject to change.
# In particular, arion-base should use a generic non-service image building system
{ config, lib, pkgs, ... }:
let
name = "arion-base";
imageExe = pkgs.dockerTools.streamLayeredImage {
inherit name;
contents = pkgs.runCommand "minimal-contents" {} ''
mkdir -p $out/bin $out/usr/bin
ln -s /run/system/bin/sh $out/bin/sh
ln -s /run/system/usr/bin/env $out/usr/bin/env
'';
config = {};
};
inherit (imageExe) imageTag;
in
{
options = {
arionBaseImage = lib.mkOption {
type = lib.types.str;
description = "Image to use when using useHostStore. Don't use this option yourself. It's going away.";
internal = true;
};
};
config = {
arionBaseImage = "${name}:${imageTag}";
build.imagesToLoad = lib.mkIf (lib.any (s: s.service.useHostStore) (lib.attrValues config.services)) [
{ imageExe = imageExe; imageName = name; inherit imageTag; }
];
};
}

View file

@ -29,12 +29,10 @@ in
}; };
}; };
config = mkIf config.service.useHostStore { config = mkIf config.service.useHostStore {
image.nixBuild = false; # no need to build and load image.includeStorePaths = false;
service.image = config.composition.arionBaseImage;
service.environment.NIX_REMOTE = lib.optionalString config.service.useHostNixDaemon "daemon"; service.environment.NIX_REMOTE = lib.optionalString config.service.useHostNixDaemon "daemon";
service.volumes = [ service.volumes = [
"${config.host.nixStorePrefix}/nix/store:/nix/store${lib.optionalString config.service.hostStoreAsReadOnly ":ro"}" "${config.host.nixStorePrefix}/nix/store:/nix/store${lib.optionalString config.service.hostStoreAsReadOnly ":ro"}"
"${config.host.nixStorePrefix}${pkgs.buildEnv { name = "container-system-env"; paths = [ pkgs.bashInteractive pkgs.coreutils ]; }}:/run/system${lib.optionalString config.service.hostStoreAsReadOnly ":ro"}"
] ++ lib.optional config.service.useHostNixDaemon "/nix/var/nix/daemon-socket:/nix/var/nix/daemon-socket"; ] ++ lib.optional config.service.useHostNixDaemon "/nix/var/nix/daemon-socket:/nix/var/nix/daemon-socket";
service.command = lib.mkDefault (map escape (config.image.rawConfig.Cmd or [])); service.command = lib.mkDefault (map escape (config.image.rawConfig.Cmd or []));
}; };

View file

@ -1,6 +1,15 @@
{ pkgs, lib, config, options, ... }: { pkgs, lib, config, options, ... }:
let let
inherit (lib) types mkOption; inherit (lib)
functionArgs
mkOption
optionalAttrs
types
warn
;
inherit (pkgs)
dockerTools
;
inherit (types) attrsOf listOf nullOr package str unspecified bool; inherit (types) attrsOf listOf nullOr package str unspecified bool;
# TODO: dummy-config is a useless layer. Nix 2.3 will let us inspect # TODO: dummy-config is a useless layer. Nix 2.3 will let us inspect
@ -9,15 +18,37 @@ let
(pkgs.writeText "dummy-config.json" (builtins.toJSON config.image.rawConfig)) (pkgs.writeText "dummy-config.json" (builtins.toJSON config.image.rawConfig))
]; ];
includeStorePathsWarningAndDefault = lib.warn ''
You're using a version of Nixpkgs that doesn't support the includeStorePaths
parameter in dockerTools.streamLayeredImage. Without this, Arion's
useHostStore does not achieve the intended speedup.
'' {};
buildOrStreamLayeredImage = args: buildOrStreamLayeredImage = args:
if pkgs.dockerTools?streamLayeredImage let
then pkgs.dockerTools.streamLayeredImage args // { isExe = true; } args_base = builtins.intersectAttrs
else pkgs.dockerTools.buildLayeredImage args; {
name = null; tag = null; contents = null; config = null;
created = null; extraCommands = null; maxLayers = null;
}
args;
acceptedArgs = functionArgs dockerTools.streamLayeredImage;
args_no_store = lib.optionalAttrs (!(args.includeStorePaths or true)) (
if acceptedArgs ? includeStorePaths
then { inherit (args) includeStorePaths; }
else includeStorePathsWarningAndDefault
);
args_streamLayered = args_base // args_no_store;
in
if dockerTools?streamLayeredImage
then dockerTools.streamLayeredImage args_streamLayered // { isExe = true; }
else dockerTools.buildLayeredImage args_base;
builtImage = buildOrStreamLayeredImage { builtImage = buildOrStreamLayeredImage {
inherit (config.image) inherit (config.image)
name name
contents contents
includeStorePaths
; ;
config = config.image.rawConfig; config = config.image.rawConfig;
maxLayers = 100; maxLayers = 100;
@ -89,6 +120,15 @@ in
Top level paths in the container. Top level paths in the container.
''; '';
}; };
image.includeStorePaths = mkOption {
type = bool;
default = true;
internal = true;
description = ''
Include all referenced store paths. You generally want this in your
image, unless you load store paths via some other means, like useHostStore = true;
'';
};
image.rawConfig = mkOption { image.rawConfig = mkOption {
type = attrsOf unspecified; type = attrsOf unspecified;
default = {}; default = {};