3
0
Fork 0
forked from mirrors/nixpkgs

dockerTools.buildImage: Add copyToRoot to replace contents, explain usage

This commit is contained in:
Robert Hensing 2022-07-01 15:02:00 +02:00
parent 72f17cca89
commit e007eb480c
6 changed files with 128 additions and 40 deletions

View file

@ -20,7 +20,12 @@ buildImage {
fromImageName = null; fromImageName = null;
fromImageTag = "latest"; fromImageTag = "latest";
contents = pkgs.redis; copyToRoot = pkgs.buildEnv {
name = "image-root";
paths = [ pkgs.redis ];
pathsToLink = [ "/bin" ];
};
runAsRoot = '' runAsRoot = ''
#!${pkgs.runtimeShell} #!${pkgs.runtimeShell}
mkdir -p /data mkdir -p /data
@ -46,7 +51,7 @@ The above example will build a Docker image `redis/latest` from the given base i
- `fromImageTag` can be used to further specify the tag of the base image within the repository, in case an image contains multiple tags. By default it's `null`, in which case `buildImage` will peek the first tag available for the base image. - `fromImageTag` can be used to further specify the tag of the base image within the repository, in case an image contains multiple tags. By default it's `null`, in which case `buildImage` will peek the first tag available for the base image.
- `contents` is a derivation that will be copied in the new layer of the resulting image. This can be similarly seen as `ADD contents/ /` in a `Dockerfile`. By default it's `null`. - `copyToRoot` is a derivation that will be copied in the new layer of the resulting image. This can be similarly seen as `ADD contents/ /` in a `Dockerfile`. By default it's `null`.
- `runAsRoot` is a bash script that will run as root in an environment that overlays the existing layers of the base image with the new resulting layer, including the previously copied `contents` derivation. This can be similarly seen as `RUN ...` in a `Dockerfile`. - `runAsRoot` is a bash script that will run as root in an environment that overlays the existing layers of the base image with the new resulting layer, including the previously copied `contents` derivation. This can be similarly seen as `RUN ...` in a `Dockerfile`.
@ -81,7 +86,11 @@ pkgs.dockerTools.buildImage {
name = "hello"; name = "hello";
tag = "latest"; tag = "latest";
created = "now"; created = "now";
contents = pkgs.hello; copyToRoot = pkgs.buildEnv {
name = "image-root";
paths = [ pkgs.hello ];
pathsToLink = [ "/bin" ];
};
config.Cmd = [ "/bin/hello" ]; config.Cmd = [ "/bin/hello" ];
} }

View file

@ -296,6 +296,15 @@
and require manual remediation. and require manual remediation.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
<literal>dockerTools.buildImage</literal> deprecates the
misunderstood <literal>contents</literal> parameter, in favor
of <literal>copyToRoot</literal>. Use
<literal>copyToRoot = buildEnv { ... };</literal> or similar
if you intend to add packages to <literal>/bin</literal>.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
memtest86+ was updated from 5.00-coreboot-002 to 6.00-beta2. memtest86+ was updated from 5.00-coreboot-002 to 6.00-beta2.

View file

@ -112,6 +112,9 @@ Use `configure.packages` instead.
- Matrix Synapse now requires entries in the `state_group_edges` table to be unique, in order to prevent accidentally introducing duplicate information (for example, because a database backup was restored multiple times). If your Synapse database already has duplicate rows in this table, this could fail with an error and require manual remediation. - Matrix Synapse now requires entries in the `state_group_edges` table to be unique, in order to prevent accidentally introducing duplicate information (for example, because a database backup was restored multiple times). If your Synapse database already has duplicate rows in this table, this could fail with an error and require manual remediation.
- `dockerTools.buildImage` deprecates the misunderstood `contents` parameter, in favor of `copyToRoot`.
Use `copyToRoot = buildEnv { ... };` or similar if you intend to add packages to `/bin`.
- memtest86+ was updated from 5.00-coreboot-002 to 6.00-beta2. It is now the upstream version from https://www.memtest.org/, as coreboot's fork is no longer available. - memtest86+ was updated from 5.00-coreboot-002 to 6.00-beta2. It is now the upstream version from https://www.memtest.org/, as coreboot's fork is no longer available.
- There is a new module for the `thunar` program (the Xfce file manager), which depends on the `xfconf` dbus service, and also has a dbus service and a systemd unit. The option `services.xserver.desktopManager.xfce.thunarPlugins` has been renamed to `programs.thunar.plugins`, and in a future release it may be removed. - There is a new module for the `thunar` program (the Xfce file manager), which depends on the `xfconf` dbus service, and also has a dbus service and a systemd unit. The option `services.xserver.desktopManager.xfce.thunarPlugins` has been renamed to `programs.thunar.plugins`, and in a future release it may be removed.

View file

@ -24,7 +24,11 @@ let
hello1 = remoteCrossPkgs.dockerTools.buildImage { hello1 = remoteCrossPkgs.dockerTools.buildImage {
name = "hello1"; name = "hello1";
tag = "latest"; tag = "latest";
contents = remoteCrossPkgs.hello; copyToRoot = remoteCrossPkgs.buildEnv {
name = "image-root";
pathsToLink = [ "/bin" ];
paths = [ remoteCrossPkgs.hello ];
};
}; };
hello2 = remoteCrossPkgs.dockerTools.buildLayeredImage { hello2 = remoteCrossPkgs.dockerTools.buildLayeredImage {

View file

@ -332,7 +332,7 @@ rec {
, # JSON containing configuration and metadata for this layer. , # JSON containing configuration and metadata for this layer.
baseJson baseJson
, # Files to add to the layer. , # Files to add to the layer.
contents ? null copyToRoot ? null
, # When copying the contents into the image, preserve symlinks to , # When copying the contents into the image, preserve symlinks to
# directories (see `rsync -K`). Otherwise, transform those symlinks # directories (see `rsync -K`). Otherwise, transform those symlinks
# into directories. # into directories.
@ -344,7 +344,8 @@ rec {
}: }:
runCommand "docker-layer-${name}" runCommand "docker-layer-${name}"
{ {
inherit baseJson contents extraCommands; inherit baseJson extraCommands;
contents = copyToRoot;
nativeBuildInputs = [ jshon rsync tarsum ]; nativeBuildInputs = [ jshon rsync tarsum ];
} }
'' ''
@ -390,7 +391,8 @@ rec {
, # Script to run as root. Bash. , # Script to run as root. Bash.
runAsRoot runAsRoot
, # Files to add to the layer. If null, an empty layer will be created. , # Files to add to the layer. If null, an empty layer will be created.
contents ? null # To add packages to /bin, use `buildEnv` or similar.
copyToRoot ? null
, # When copying the contents into the image, preserve symlinks to , # When copying the contents into the image, preserve symlinks to
# directories (see `rsync -K`). Otherwise, transform those symlinks # directories (see `rsync -K`). Otherwise, transform those symlinks
# into directories. # into directories.
@ -418,9 +420,9 @@ rec {
inherit fromImage fromImageName fromImageTag diskSize; inherit fromImage fromImageName fromImageTag diskSize;
preMount = lib.optionalString (contents != null && contents != [ ]) '' preMount = lib.optionalString (copyToRoot != null && copyToRoot != [ ]) ''
echo "Adding contents..." echo "Adding contents..."
for item in ${escapeShellArgs (map (c: "${c}") (toList contents))}; do for item in ${escapeShellArgs (map (c: "${c}") (toList copyToRoot))}; do
echo "Adding $item..." echo "Adding $item..."
rsync -a${if keepContentsDirlinks then "K" else "k"} --chown=0:0 $item/ layer/ rsync -a${if keepContentsDirlinks then "K" else "k"} --chown=0:0 $item/ layer/
done done
@ -500,7 +502,7 @@ rec {
, # Tag of the parent image; will be read from the image otherwise. , # Tag of the parent image; will be read from the image otherwise.
fromImageTag ? null fromImageTag ? null
, # Files to put on the image (a nix store path or list of paths). , # Files to put on the image (a nix store path or list of paths).
contents ? null copyToRoot ? null
, # When copying the contents into the image, preserve symlinks to , # When copying the contents into the image, preserve symlinks to
# directories (see `rsync -K`). Otherwise, transform those symlinks # directories (see `rsync -K`). Otherwise, transform those symlinks
# into directories. # into directories.
@ -517,10 +519,20 @@ rec {
diskSize ? 1024 diskSize ? 1024
, # Time of creation of the image. , # Time of creation of the image.
created ? "1970-01-01T00:00:01Z" created ? "1970-01-01T00:00:01Z"
, # Deprecated.
contents ? null
, ,
}: }:
let let
checked =
lib.warnIf (contents != null)
"in docker image ${name}: The contents parameter is deprecated. Change to copyToRoot if the contents are designed to be copied to the root filesystem, such as when you use `buildEnv` or similar between contents and your packages. Use copyToRoot = buildEnv { ... }; or similar if you intend to add packages to /bin."
lib.throwIf (contents != null && copyToRoot != null) "in docker image ${name}: You can not specify both contents and copyToRoot."
;
rootContents = if copyToRoot == null then contents else copyToRoot;
baseName = baseNameOf name; baseName = baseNameOf name;
# Create a JSON blob of the configuration. Set the date to unix zero. # Create a JSON blob of the configuration. Set the date to unix zero.
@ -545,13 +557,15 @@ rec {
mkPureLayer mkPureLayer
{ {
name = baseName; name = baseName;
inherit baseJson contents keepContentsDirlinks extraCommands uid gid; inherit baseJson keepContentsDirlinks extraCommands uid gid;
copyToRoot = rootContents;
} else } else
mkRootLayer { mkRootLayer {
name = baseName; name = baseName;
inherit baseJson fromImage fromImageName fromImageTag inherit baseJson fromImage fromImageName fromImageTag
contents keepContentsDirlinks runAsRoot diskSize keepContentsDirlinks runAsRoot diskSize
extraCommands; extraCommands;
copyToRoot = rootContents;
}; };
result = runCommand "docker-image-${baseName}.tar.gz" result = runCommand "docker-image-${baseName}.tar.gz"
{ {
@ -715,7 +729,7 @@ rec {
''; '';
in in
result; checked result;
# Merge the tarballs of images built with buildImage into a single # Merge the tarballs of images built with buildImage into a single
# tarball that contains all images. Running `docker load` on the resulting # tarball that contains all images. Running `docker load` on the resulting
@ -776,12 +790,14 @@ rec {
# contents. The main purpose is to be able to use nix commands in # contents. The main purpose is to be able to use nix commands in
# the container. # the container.
# Be careful since this doesn't work well with multilayer. # Be careful since this doesn't work well with multilayer.
buildImageWithNixDb = args@{ contents ? null, extraCommands ? "", ... }: ( # TODO: add the dependencies of the config json.
buildImageWithNixDb = args@{ copyToRoot ? contents, contents ? null, extraCommands ? "", ... }: (
buildImage (args // { buildImage (args // {
extraCommands = (mkDbExtraCommand contents) + extraCommands; extraCommands = (mkDbExtraCommand copyToRoot) + extraCommands;
}) })
); );
# TODO: add the dependencies of the config json.
buildLayeredImageWithNixDb = args@{ contents ? null, extraCommands ? "", ... }: ( buildLayeredImageWithNixDb = args@{ contents ? null, extraCommands ? "", ... }: (
buildLayeredImage (args // { buildLayeredImage (args // {
extraCommands = (mkDbExtraCommand contents) + extraCommands; extraCommands = (mkDbExtraCommand contents) + extraCommands;

View file

@ -24,7 +24,11 @@ rec {
bash = buildImage { bash = buildImage {
name = "bash"; name = "bash";
tag = "latest"; tag = "latest";
contents = pkgs.bashInteractive; copyToRoot = pkgs.buildEnv {
name = "image-root";
paths = [ pkgs.bashInteractive ];
pathsToLink = [ "/bin" ];
};
}; };
# 2. service example, layered on another image # 2. service example, layered on another image
@ -36,7 +40,12 @@ rec {
fromImage = bash; fromImage = bash;
# fromImage = debian; # fromImage = debian;
contents = pkgs.redis; copyToRoot = pkgs.buildEnv {
name = "image-root";
paths = [ pkgs.redis ];
pathsToLink = [ "/bin" ];
};
runAsRoot = '' runAsRoot = ''
mkdir -p /data mkdir -p /data
''; '';
@ -118,13 +127,17 @@ rec {
# 5. example of multiple contents, emacs and vi happily coexisting # 5. example of multiple contents, emacs and vi happily coexisting
editors = buildImage { editors = buildImage {
name = "editors"; name = "editors";
contents = [ copyToRoot = pkgs.buildEnv {
pkgs.coreutils name = "image-root";
pkgs.bash pathsToLink = [ "/bin" ];
pkgs.emacs paths = [
pkgs.vim pkgs.coreutils
pkgs.nano pkgs.bash
]; pkgs.emacs
pkgs.vim
pkgs.nano
];
};
}; };
# 6. nix example to play with the container nix store # 6. nix example to play with the container nix store
@ -132,13 +145,17 @@ rec {
nix = buildImageWithNixDb { nix = buildImageWithNixDb {
name = "nix"; name = "nix";
tag = "latest"; tag = "latest";
contents = [ copyToRoot = pkgs.buildEnv {
# nix-store uses cat program to display results as specified by name = "image-root";
# the image env variable NIX_PAGER. pathsToLink = [ "/bin" ];
pkgs.coreutils paths = [
pkgs.nix # nix-store uses cat program to display results as specified by
pkgs.bash # the image env variable NIX_PAGER.
]; pkgs.coreutils
pkgs.nix
pkgs.bash
];
};
config = { config = {
Env = [ Env = [
"NIX_PAGER=cat" "NIX_PAGER=cat"
@ -155,7 +172,11 @@ rec {
name = "onTopOfPulledImage"; name = "onTopOfPulledImage";
tag = "latest"; tag = "latest";
fromImage = nixFromDockerHub; fromImage = nixFromDockerHub;
contents = [ pkgs.hello ]; copyToRoot = pkgs.buildEnv {
name = "image-root";
pathsToLink = [ "/bin" ];
paths = [ pkgs.hello ];
};
}; };
# 8. regression test for erroneous use of eval and string expansion. # 8. regression test for erroneous use of eval and string expansion.
@ -163,7 +184,11 @@ rec {
runAsRootExtraCommands = pkgs.dockerTools.buildImage { runAsRootExtraCommands = pkgs.dockerTools.buildImage {
name = "runAsRootExtraCommands"; name = "runAsRootExtraCommands";
tag = "latest"; tag = "latest";
contents = [ pkgs.coreutils ]; copyToRoot = pkgs.buildEnv {
name = "image-root";
pathsToLink = [ "/bin" ];
paths = [ pkgs.coreutils ];
};
# The parens here are to create problematic bash to embed and eval. In case # The parens here are to create problematic bash to embed and eval. In case
# this is *embedded* into the script (with nix expansion) the initial quotes # this is *embedded* into the script (with nix expansion) the initial quotes
# will close the string and the following parens are unexpected # will close the string and the following parens are unexpected
@ -176,7 +201,11 @@ rec {
unstableDate = pkgs.dockerTools.buildImage { unstableDate = pkgs.dockerTools.buildImage {
name = "unstable-date"; name = "unstable-date";
tag = "latest"; tag = "latest";
contents = [ pkgs.coreutils ]; copyToRoot = pkgs.buildEnv {
name = "image-root";
pathsToLink = [ "/bin" ];
paths = [ pkgs.coreutils ];
};
created = "now"; created = "now";
}; };
@ -265,7 +294,11 @@ rec {
name = "l3"; name = "l3";
fromImage = l2; fromImage = l2;
tag = "latest"; tag = "latest";
contents = [ pkgs.coreutils ]; copyToRoot = pkgs.buildEnv {
name = "image-root";
pathsToLink = [ "/bin" ];
paths = [ pkgs.coreutils ];
};
extraCommands = '' extraCommands = ''
mkdir -p tmp mkdir -p tmp
echo layer3 > tmp/layer3 echo layer3 > tmp/layer3
@ -290,7 +323,11 @@ rec {
name = "child"; name = "child";
fromImage = environmentVariablesParent; fromImage = environmentVariablesParent;
tag = "latest"; tag = "latest";
contents = [ pkgs.coreutils ]; copyToRoot = pkgs.buildEnv {
name = "image-root";
pathsToLink = [ "/bin" ];
paths = [ pkgs.coreutils ];
};
config = { config = {
Env = [ Env = [
"FROM_CHILD=true" "FROM_CHILD=true"
@ -424,7 +461,11 @@ rec {
name = "layers-unpack-order-${layerName}"; name = "layers-unpack-order-${layerName}";
tag = "latest"; tag = "latest";
fromImage = parent; fromImage = parent;
contents = [ pkgs.coreutils ]; copyToRoot = pkgs.buildEnv {
name = "image-root";
pathsToLink = [ "/bin" ];
paths = [ pkgs.coreutils ];
};
runAsRoot = '' runAsRoot = ''
#!${pkgs.runtimeShell} #!${pkgs.runtimeShell}
echo -n "${layerName}" >> /layer-order echo -n "${layerName}" >> /layer-order
@ -441,7 +482,8 @@ rec {
# buildImage without explicit tag # buildImage without explicit tag
bashNoTag = pkgs.dockerTools.buildImage { bashNoTag = pkgs.dockerTools.buildImage {
name = "bash-no-tag"; name = "bash-no-tag";
contents = pkgs.bashInteractive; # Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
copyToRoot = pkgs.bashInteractive;
}; };
# buildLayeredImage without explicit tag # buildLayeredImage without explicit tag
@ -501,7 +543,11 @@ rec {
in crossPkgs.dockerTools.buildImage { in crossPkgs.dockerTools.buildImage {
name = "hello-cross"; name = "hello-cross";
tag = "latest"; tag = "latest";
contents = crossPkgs.hello; copyToRoot = pkgs.buildEnv {
name = "image-root";
pathsToLink = [ "/bin" ];
paths = [ crossPkgs.hello ];
};
}; };
# layered image where a store path is itself a symlink # layered image where a store path is itself a symlink
@ -643,7 +689,8 @@ rec {
build-image-with-path = buildImage { build-image-with-path = buildImage {
name = "build-image-with-path"; name = "build-image-with-path";
tag = "latest"; tag = "latest";
contents = [ pkgs.bashInteractive ./test-dummy ]; # Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
copyToRoot = [ pkgs.bashInteractive ./test-dummy ];
}; };
layered-image-with-path = pkgs.dockerTools.streamLayeredImage { layered-image-with-path = pkgs.dockerTools.streamLayeredImage {