Merge pull request #116749 from vroad/docker-layered-image-fakeroot

dockerTools.streamLayeredImage: add fakeRootCommands option
This commit is contained in:
Robert Hensing 2021-04-07 15:02:24 +02:00 committed by GitHub
commit 58b21dea78
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 7 deletions

View file

@ -147,6 +147,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, 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}
Each path directly listed in `contents` will have a symlink in the root of the image.

View file

@ -313,5 +313,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$'"
)
'';
})

View file

@ -7,6 +7,7 @@
coreutils,
docker,
e2fsprogs,
fakeroot,
findutils,
go,
jq,
@ -740,6 +741,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
@ -765,19 +769,24 @@ rec {
customisationLayer = symlinkJoin {
name = "${baseName}-customisation-layer";
paths = contentsList;
inherit extraCommands;
inherit extraCommands 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 '
source $stdenv/setup
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 ' ' \

View file

@ -484,4 +484,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
'';
};
}