From b4d92811befd66f5ab86450b650e6f6c033f956b Mon Sep 17 00:00:00 2001 From: vroad <396351+vroad@users.noreply.github.com> Date: Fri, 19 Mar 2021 10:25:26 +0900 Subject: [PATCH 1/6] dockerTools.streamLayeredImage: add fakeRootCommands option --- pkgs/build-support/docker/default.nix | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix index fec289f0ff1..8453ea4deed 100644 --- a/pkgs/build-support/docker/default.nix +++ b/pkgs/build-support/docker/default.nix @@ -7,6 +7,7 @@ coreutils, docker, e2fsprogs, + fakeroot, findutils, go, jq, @@ -738,6 +739,9 @@ rec { created ? "1970-01-01T00:00:01Z", # Optional bash script to run on the files prior to fixturizing the layer. extraCommands ? "", + # Optional bash script to run inside fakeroot environment. + # Could be used for changing ownership of files in customisation layer. + fakeRootCommands ? "", # We pick 100 to ensure there is plenty of room for extension. I # believe the actual maximum is 128. maxLayers ? 100 @@ -764,18 +768,24 @@ rec { name = "${baseName}-customisation-layer"; paths = contentsList; inherit extraCommands; + inherit fakeRootCommands; + nativeBuildInputs = [ fakeroot ]; postBuild = '' mv $out old_out (cd old_out; eval "$extraCommands" ) mkdir $out - tar \ - --sort name \ - --owner 0 --group 0 --mtime "@$SOURCE_DATE_EPOCH" \ - --hard-dereference \ - -C old_out \ - -cf $out/layer.tar . + fakeroot bash -c ' + set -e + cd old_out + eval "$fakeRootCommands" + tar \ + --sort name \ + --numeric-owner --mtime "@$SOURCE_DATE_EPOCH" \ + --hard-dereference \ + -cf $out/layer.tar . + ' sha256sum $out/layer.tar \ | cut -f 1 -d ' ' \ From 5199c7e6da7eb0d87744a04fdbda50e40e902e2e Mon Sep 17 00:00:00 2001 From: vroad <396351+vroad@users.noreply.github.com> Date: Fri, 19 Mar 2021 10:56:00 +0900 Subject: [PATCH 2/6] dockerTools.streamLayeredImage: simplify inherit statements Co-authored-by: Sandro --- pkgs/build-support/docker/default.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix index 8453ea4deed..bf0b512fa1e 100644 --- a/pkgs/build-support/docker/default.nix +++ b/pkgs/build-support/docker/default.nix @@ -767,8 +767,7 @@ rec { customisationLayer = symlinkJoin { name = "${baseName}-customisation-layer"; paths = contentsList; - inherit extraCommands; - inherit fakeRootCommands; + inherit extraCommands fakeRootCommands; nativeBuildInputs = [ fakeroot ]; postBuild = '' mv $out old_out From 057c7a2d58d28fc63c733728a591d7ecd30755ca Mon Sep 17 00:00:00 2001 From: vroad <396351+vroad@users.noreply.github.com> Date: Fri, 19 Mar 2021 11:01:10 +0900 Subject: [PATCH 3/6] dockerTools.streamLayeredImage: source $stdenv/setup before running fakeRootCommands --- pkgs/build-support/docker/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix index bf0b512fa1e..7837406f8d4 100644 --- a/pkgs/build-support/docker/default.nix +++ b/pkgs/build-support/docker/default.nix @@ -776,7 +776,7 @@ rec { mkdir $out fakeroot bash -c ' - set -e + source $stdenv/setup cd old_out eval "$fakeRootCommands" tar \ From 2dce2253bcf4b1b7eacd823783d1abedb857234f Mon Sep 17 00:00:00 2001 From: vroad <396351+vroad@users.noreply.github.com> Date: Fri, 19 Mar 2021 11:54:13 +0900 Subject: [PATCH 4/6] dockerTools.streamLayeredImage: document fakeRootCommands --- doc/builders/images/dockertools.section.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/builders/images/dockertools.section.md b/doc/builders/images/dockertools.section.md index 40d4dba1b85..99b901e9b86 100644 --- a/doc/builders/images/dockertools.section.md +++ b/doc/builders/images/dockertools.section.md @@ -141,6 +141,10 @@ Create a Docker image with many of the store paths being on their own layer to i : Shell commands to run while building the final layer, without access to most of the layer contents. Changes to this layer are "on top" of all the other layers, so can create additional directories and files. +`fakeRootCommands` _optional_ + +: Shell commands to run while creating the archive for the final layer in a fakeroot environment. Unlike `extraCommands`, you can run chown to change the owners of the files in the archive, without actually persisting the change to the filesystem. By default all files in the archive will be owned by root. + ### Behavior of `contents` in the final image {#dockerTools-buildLayeredImage-arg-contents} Each path directly listed in `contents` will have a symlink in the root of the image. From c420e650c9d230fe9329f2ec9ad5b4cad5c21f5d Mon Sep 17 00:00:00 2001 From: vroad <396351+vroad@users.noreply.github.com> Date: Wed, 24 Mar 2021 08:24:21 +0900 Subject: [PATCH 5/6] dockerTools.streamLayeredImage: Update documentation Co-authored-by: Robert Hensing --- doc/builders/images/dockertools.section.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/builders/images/dockertools.section.md b/doc/builders/images/dockertools.section.md index 99b901e9b86..2573fc272f7 100644 --- a/doc/builders/images/dockertools.section.md +++ b/doc/builders/images/dockertools.section.md @@ -143,7 +143,7 @@ Create a Docker image with many of the store paths being on their own layer to i `fakeRootCommands` _optional_ -: Shell commands to run while creating the archive for the final layer in a fakeroot environment. Unlike `extraCommands`, you can run chown to change the owners of the files in the archive, without actually persisting the change to the filesystem. By default all files in the archive will be owned by root. +: Shell commands to run while creating the archive for the final layer in a fakeroot environment. Unlike `extraCommands`, you can run `chown` to change the owners of the files in the archive, changing fakeroot's state instead of the real filesystem. The latter would require privileges that the build user does not have. Static binaries do not interact with the fakeroot environment. By default all files in the archive will be owned by root. ### Behavior of `contents` in the final image {#dockerTools-buildLayeredImage-arg-contents} From 63e7c4186f43190ca4ee44aeec10f81343573861 Mon Sep 17 00:00:00 2001 From: vroad <396351+vroad@users.noreply.github.com> Date: Wed, 7 Apr 2021 18:11:02 +0900 Subject: [PATCH 6/6] dockerTools.streamLayeredImage: Add test for fakeRootCommands --- nixos/tests/docker-tools.nix | 8 ++++++++ pkgs/build-support/docker/examples.nix | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/nixos/tests/docker-tools.nix b/nixos/tests/docker-tools.nix index 1cc554d002b..a71cf79c5a7 100644 --- a/nixos/tests/docker-tools.nix +++ b/nixos/tests/docker-tools.nix @@ -270,5 +270,13 @@ import ./make-test-python.nix ({ pkgs, ... }: { docker.succeed( "docker images --format '{{.Repository}}' | grep -F '${examples.prefixedLayeredImage.imageName}'" ) + + with subtest("buildLayeredImage supports running chown with fakeRootCommands"): + docker.succeed( + "docker load --input='${examples.layeredImageWithFakeRootCommands}'" + ) + docker.succeed( + "docker run --rm ${examples.layeredImageWithFakeRootCommands.imageName} sh -c 'stat -c '%u' /home/jane | grep -E ^1000$'" + ) ''; }) diff --git a/pkgs/build-support/docker/examples.nix b/pkgs/build-support/docker/examples.nix index 9e33a42af23..2eab0ede023 100644 --- a/pkgs/build-support/docker/examples.nix +++ b/pkgs/build-support/docker/examples.nix @@ -441,4 +441,17 @@ rec { tag = "latest"; config.Cmd = [ "${pkgs.hello}/bin/hello" ]; }; + + # layered image with files owned by a user other than root + layeredImageWithFakeRootCommands = pkgs.dockerTools.buildLayeredImage { + name = "layered-image-with-fake-root-commands"; + tag = "latest"; + contents = [ + pkgs.pkgsStatic.busybox + ]; + fakeRootCommands = '' + mkdir -p ./home/jane + chown 1000 ./home/jane + ''; + }; }