feat: support using arbitrary image tarballs
Via the `services.<name>.image.tarball` option. This permits users to supply any valid image archive, potentially (but not necessarily) generated by a builder function from `pkgs.dockerTools`.
This commit is contained in:
parent
add0e67d2b
commit
fc14ff7abf
1 changed files with 128 additions and 3 deletions
|
@ -1,7 +1,11 @@
|
|||
{ pkgs, lib, config, options, ... }:
|
||||
let
|
||||
inherit (lib)
|
||||
all
|
||||
flip
|
||||
functionArgs
|
||||
hasAttr
|
||||
isDerivation
|
||||
mkOption
|
||||
optionalAttrs
|
||||
types
|
||||
|
@ -10,7 +14,20 @@ let
|
|||
inherit (pkgs)
|
||||
dockerTools
|
||||
;
|
||||
inherit (types) attrsOf listOf nullOr package str unspecified bool;
|
||||
inherit (types)
|
||||
addCheck
|
||||
attrs
|
||||
attrsOf
|
||||
bool
|
||||
coercedTo
|
||||
listOf
|
||||
nullOr
|
||||
oneOf
|
||||
package
|
||||
path
|
||||
str
|
||||
unspecified
|
||||
;
|
||||
|
||||
# TODO: dummy-config is a useless layer. Nix 2.3 will let us inspect
|
||||
# the string context instead, so we can avoid this.
|
||||
|
@ -18,6 +35,41 @@ let
|
|||
(pkgs.writeText "dummy-config.json" (builtins.toJSON config.image.rawConfig))
|
||||
];
|
||||
|
||||
# Shim for `services.<name>.image.tarball` definitions that refer to
|
||||
# arbitrary paths and not `dockerTools`-produced derivations.
|
||||
dummyImagePackage = outPath: {
|
||||
inherit outPath;
|
||||
type = "derivation";
|
||||
imageName = config.image.name;
|
||||
imageTag = if config.image.tag == null then "" else config.image.tag;
|
||||
};
|
||||
|
||||
# Type matching the essential attributes of derivations produced by
|
||||
# `dockerTools` builder functions.
|
||||
imagePackageType = addCheck attrs (x: isDerivation x && (all (flip hasAttr x) [ "imageName" "imageTag" ]));
|
||||
|
||||
# `coercedTo path dummyImagePackage package` looks sufficient, but it is not.
|
||||
# `coercedTo` defines this `check` function:
|
||||
#
|
||||
# x: (coercedType.check x && finalType.check (coerceFunc x)) || finalType.check x;
|
||||
#
|
||||
# and this `merge` function:
|
||||
#
|
||||
# loc: defs:
|
||||
# let
|
||||
# coerceVal = val:
|
||||
# if coercedType.check val then coerceFunc val
|
||||
# else val;
|
||||
# in finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
|
||||
#
|
||||
# Meaning that values that satisfy `finalType.check` may still be subject to
|
||||
# coercion. In this case, derivations satisfy `path.check`, so will be
|
||||
# coerced using the `dummyImagePackage` function. To avoid this unnecessary
|
||||
# coercion, we instead force checking whether the value satisfies
|
||||
# `imagePackageType.check` *first* via placing `imagePackageType` at the head
|
||||
# of the list provided to `oneOf`.
|
||||
imageTarballType = oneOf [ imagePackageType (coercedTo path dummyImagePackage imagePackageType) ];
|
||||
|
||||
includeStorePathsWarningAndDefault = lib.warn ''
|
||||
You're using a version of Nixpkgs that doesn't support the includeStorePaths
|
||||
parameter in dockerTools.streamLayeredImage. Without this, Arion's
|
||||
|
@ -48,6 +100,7 @@ let
|
|||
builtImage = buildOrStreamLayeredImage {
|
||||
inherit (config.image)
|
||||
name
|
||||
tag
|
||||
contents
|
||||
includeStorePaths
|
||||
;
|
||||
|
@ -80,6 +133,16 @@ in
|
|||
type = nullOr package;
|
||||
description = ''
|
||||
Docker image derivation to be `docker load`-ed.
|
||||
|
||||
By default, when `services.<name>.image.nixBuild` is enabled, this is
|
||||
the image produced using `services.<name>.image.command`,
|
||||
`services.<name>.image.contents`, and
|
||||
`services.<name>.image.rawConfig`.
|
||||
'';
|
||||
defaultText = lib.literalExample ''
|
||||
pkgs.dockerTools.buildLayeredImage {
|
||||
# ...
|
||||
};
|
||||
'';
|
||||
internal = true;
|
||||
};
|
||||
|
@ -110,10 +173,39 @@ in
|
|||
default = "localhost/" + config.service.name;
|
||||
defaultText = lib.literalExpression or lib.literalExample ''"localhost/" + config.service.name'';
|
||||
description = ''
|
||||
A human readable name for the docker image.
|
||||
A human readable name for the Docker image.
|
||||
|
||||
Shows up in the `docker ps` output in the
|
||||
`IMAGE` column, among other places.
|
||||
|
||||
::: {.important}
|
||||
If you set {option}`services.<name>.image.tarball` to an arbitrary
|
||||
Docker image tarball (and not, say, a derivation produced by one of the
|
||||
[`dockerTools`](https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-dockerTools)
|
||||
builder functions), then you **must** set {option}`services.<name>.image.name`
|
||||
to the name of the image in the tarball. Otherwise, Arion will not be
|
||||
able to properly identify the image in the generated Docker Compose
|
||||
configuration file.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
image.tag = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
A tag to assign to the built image, or (if you specified an image archive
|
||||
with `image.tarball`) the tag that arion should use when referring to
|
||||
the loaded image.
|
||||
|
||||
::: {.important}
|
||||
If you set {option}`services.<name>.image.tarball` to an arbitrary
|
||||
Docker image tarball (and not, say, a derivation produced by one of the
|
||||
[`dockerTools`](https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-dockerTools)
|
||||
builder functions), then you **must** set {option}`services.<name>.image.tag`
|
||||
to one of the tags associated with `services.<name>.image.name` in the
|
||||
image tarball. Otherwise, Arion will not be able to properly identify
|
||||
the image in the generated Docker Compose configuration file.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
image.contents = mkOption {
|
||||
|
@ -162,9 +254,42 @@ in
|
|||
description = ''
|
||||
'';
|
||||
};
|
||||
image.tarball = mkOption {
|
||||
type = nullOr imageTarballType;
|
||||
default = builtImage;
|
||||
defaultText = "${builtins.storeDir}/image-built-from-service-configuration.tar.gz";
|
||||
description = ''
|
||||
Docker image tarball to be `docker load`-ed. This can be a derivation
|
||||
produced with one of the [`dockerTools`](https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-dockerTools)
|
||||
builder functions, or a Docker image tarball at some arbitrary
|
||||
location.
|
||||
|
||||
::: {.note}
|
||||
Using this option causes Arion to ignore most other options in the
|
||||
{option}`services.<name>.image` namespace. The exceptions are
|
||||
{option}`services.<name>.image.name` and {option}`services.<name>.image.tag`,
|
||||
which are used when the provided {option}`services.<name>.image.tarball`
|
||||
is not a derivation with the attributes `imageName` and `imageTag`.
|
||||
:::
|
||||
'';
|
||||
example = lib.literalExample or lib.literalExpression ''
|
||||
let
|
||||
myimage = pkgs.dockerTools.buildImage {
|
||||
name = "my-image";
|
||||
contents = [ pkgs.coreutils ];
|
||||
};
|
||||
in
|
||||
config.services = {
|
||||
myservice = {
|
||||
image.tarball = myimage;
|
||||
# ...
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
config = lib.mkMerge [{
|
||||
build.image = builtImage;
|
||||
build.image = config.image.tarball;
|
||||
build.imageName = config.build.image.imageName;
|
||||
build.imageTag =
|
||||
if config.build.image.imageTag != ""
|
||||
|
|
Loading…
Reference in a new issue