Merge pull request #148363 from hercules-ci/add-dockerTools-fakechroot

dockerTools: Add fakechroot to fakeRootCommands
This commit is contained in:
Robert Hensing 2021-12-04 15:13:37 +01:00 committed by GitHub
commit 430c9173e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 4 deletions

View File

@ -151,6 +151,12 @@ Create a Docker image with many of the store paths being on their own layer to i
: 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. : 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.
`enableFakechroot` _optional_
: Whether to run in `fakeRootCommands` in `fakechroot`, making programs behave as though `/` is the root of the image being created, while files in the Nix store are available as usual. This allows scripts that perform installation in `/` to work as expected. Considering that `fakechroot` is implemented via the same mechanism as `fakeroot`, the same caveats apply.
*Default:* `false`
### Behavior of `contents` in the final image {#dockerTools-buildLayeredImage-arg-contents} ### 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. Each path directly listed in `contents` will have a symlink in the root of the image.

View File

@ -396,6 +396,11 @@ import ./make-test-python.nix ({ pkgs, ... }: {
"tar -tf ${examples.exportBash} | grep '\./bin/bash' > /dev/null" "tar -tf ${examples.exportBash} | grep '\./bin/bash' > /dev/null"
) )
with subtest("layered image fakeRootCommands with fakechroot works"):
docker.succeed("${examples.imageViaFakeChroot} | docker load")
docker.succeed("docker run --rm image-via-fake-chroot | grep -i hello")
docker.succeed("docker image rm image-via-fake-chroot:latest")
with subtest("Ensure bare paths in contents are loaded correctly"): with subtest("Ensure bare paths in contents are loaded correctly"):
docker.succeed( docker.succeed(
"docker load --input='${examples.build-image-with-path}'", "docker load --input='${examples.build-image-with-path}'",

View File

@ -5,6 +5,7 @@
, closureInfo , closureInfo
, coreutils , coreutils
, e2fsprogs , e2fsprogs
, fakechroot
, fakeroot , fakeroot
, findutils , findutils
, go , go
@ -34,6 +35,10 @@
}: }:
let let
inherit (lib)
optionals
optionalString
;
inherit (lib) inherit (lib)
escapeShellArgs escapeShellArgs
@ -811,6 +816,10 @@ rec {
, # Optional bash script to run inside fakeroot environment. , # Optional bash script to run inside fakeroot environment.
# Could be used for changing ownership of files in customisation layer. # Could be used for changing ownership of files in customisation layer.
fakeRootCommands ? "" fakeRootCommands ? ""
, # Whether to run fakeRootCommands in fakechroot as well, so that they
# appear to run inside the image, but have access to the normal Nix store.
# Perhaps this could be enabled on by default on pkgs.stdenv.buildPlatform.isLinux
enableFakechroot ? false
, # We pick 100 to ensure there is plenty of room for extension. I , # We pick 100 to ensure there is plenty of room for extension. I
# believe the actual maximum is 128. # believe the actual maximum is 128.
maxLayers ? 100 maxLayers ? 100
@ -842,16 +851,26 @@ rec {
name = "${baseName}-customisation-layer"; name = "${baseName}-customisation-layer";
paths = contentsList; paths = contentsList;
inherit extraCommands fakeRootCommands; inherit extraCommands fakeRootCommands;
nativeBuildInputs = [ fakeroot ]; nativeBuildInputs = [
fakeroot
] ++ optionals enableFakechroot [
fakechroot
# for chroot
coreutils
# fakechroot needs getopt, which is provided by util-linux
util-linux
];
postBuild = '' postBuild = ''
mv $out old_out mv $out old_out
(cd old_out; eval "$extraCommands" ) (cd old_out; eval "$extraCommands" )
mkdir $out mkdir $out
${optionalString enableFakechroot ''
fakeroot bash -c ' export FAKECHROOT_EXCLUDE_PATH=/dev:/proc:/sys:${builtins.storeDir}:$out/layer.tar
''}
${optionalString enableFakechroot ''fakechroot chroot $PWD/old_out ''}fakeroot bash -c '
source $stdenv/setup source $stdenv/setup
cd old_out ${optionalString (!enableFakechroot) ''cd old_out''}
eval "$fakeRootCommands" eval "$fakeRootCommands"
tar \ tar \
--sort name \ --sort name \

View File

@ -562,6 +562,20 @@ rec {
# Example export of the bash image # Example export of the bash image
exportBash = pkgs.dockerTools.exportImage { fromImage = bash; }; exportBash = pkgs.dockerTools.exportImage { fromImage = bash; };
imageViaFakeChroot = pkgs.dockerTools.streamLayeredImage {
name = "image-via-fake-chroot";
tag = "latest";
config.Cmd = [ "hello" ];
enableFakechroot = true;
# Crucially, instead of a relative path, this creates /bin, which is
# intercepted by fakechroot.
# This functionality is not available on darwin as of 2021.
fakeRootCommands = ''
mkdir /bin
ln -s ${pkgs.hello}/bin/hello /bin/hello
'';
};
build-image-with-path = buildImage { build-image-with-path = buildImage {
name = "build-image-with-path"; name = "build-image-with-path";
tag = "latest"; tag = "latest";