summary refs log tree commit diff
diff options
context:
space:
mode:
authorRobert Hensing <robert@roberthensing.nl>2021-10-01 15:53:30 +0200
committerRobert Hensing <robert@roberthensing.nl>2021-12-04 13:49:10 +0000
commit0e9bc9ffd107c288571af4e3d4a9c2a6b64cf505 (patch)
tree36a94f9c1ade0e988305b83b28228c38eac7eb59
parent66c19d856bb4eece4dce7f35787126dd67274acd (diff)
downloadnixpkgs-0e9bc9ffd107c288571af4e3d4a9c2a6b64cf505.tar
nixpkgs-0e9bc9ffd107c288571af4e3d4a9c2a6b64cf505.tar.gz
nixpkgs-0e9bc9ffd107c288571af4e3d4a9c2a6b64cf505.tar.bz2
nixpkgs-0e9bc9ffd107c288571af4e3d4a9c2a6b64cf505.tar.lz
nixpkgs-0e9bc9ffd107c288571af4e3d4a9c2a6b64cf505.tar.xz
nixpkgs-0e9bc9ffd107c288571af4e3d4a9c2a6b64cf505.tar.zst
nixpkgs-0e9bc9ffd107c288571af4e3d4a9c2a6b64cf505.zip
dockerTools: Add fakechroot to fakeRootCommands
-rw-r--r--doc/builders/images/dockertools.section.md8
-rw-r--r--nixos/doc/manual/from_md/release-notes/rl-2205.section.xml8
-rw-r--r--nixos/doc/manual/release-notes/rl-2205.section.md4
-rw-r--r--nixos/tests/docker-tools.nix5
-rw-r--r--pkgs/build-support/docker/default.nix26
-rw-r--r--pkgs/build-support/docker/examples.nix13
6 files changed, 59 insertions, 5 deletions
diff --git a/doc/builders/images/dockertools.section.md b/doc/builders/images/dockertools.section.md
index bfe1d17a606..af09f252223 100644
--- a/doc/builders/images/dockertools.section.md
+++ b/doc/builders/images/dockertools.section.md
@@ -149,7 +149,13 @@ 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, 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 + fakechroot 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 most scripts that perform installation in `/` to work as expected. Considering that `fakechroot` is implemented via the same mechanism as `fakeroot`, it is not guaranteed to work and will not work for static binaries.
+
+    *Default:* `true` when built on Linux, `false` otherwise
 
 ### Behavior of `contents` in the final image {#dockerTools-buildLayeredImage-arg-contents}
 
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
index 4752cad6c7b..5e6a89dc981 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
@@ -57,6 +57,14 @@
           new versions will release.
         </para>
       </listitem>
+      <listitem>
+        <para>
+          <literal>pkgs.dockerTools.buildLayeredImage</literal>/<literal>streamLayeredImage</literal>
+          enable <literal>enableFakechroot</literal> by default on
+          Linux. This might be unexpected and can be set to
+          <literal>false</literal> if image generation fails.
+        </para>
+      </listitem>
     </itemizedlist>
   </section>
   <section xml:id="sec-release-22.05-notable-changes">
diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md
index b0526a1fb3b..b774b2af2f7 100644
--- a/nixos/doc/manual/release-notes/rl-2205.section.md
+++ b/nixos/doc/manual/release-notes/rl-2205.section.md
@@ -27,4 +27,8 @@ In addition to numerous new and upgraded packages, this release has the followin
   org-contrib, refer to the ones in `pkgs.emacsPackages.elpaPackages` and
   `pkgs.emacsPackages.nongnuPackages` where the new versions will release.
 
+* `pkgs.dockerTools.buildLayeredImage`/`streamLayeredImage` enable
+  `enableFakechroot` by default on Linux.
+  This might be unexpected and can be set to `false` if image generation fails.
+
 ## Other Notable Changes {#sec-release-22.05-notable-changes}
diff --git a/nixos/tests/docker-tools.nix b/nixos/tests/docker-tools.nix
index f3858b8bd81..19ebed3ebd0 100644
--- a/nixos/tests/docker-tools.nix
+++ b/nixos/tests/docker-tools.nix
@@ -396,6 +396,11 @@ import ./make-test-python.nix ({ pkgs, ... }: {
             "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"):
         docker.succeed(
             "docker load --input='${examples.build-image-with-path}'",
diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix
index 7958db91712..a6d3109bf6d 100644
--- a/pkgs/build-support/docker/default.nix
+++ b/pkgs/build-support/docker/default.nix
@@ -5,6 +5,7 @@
 , closureInfo
 , coreutils
 , e2fsprogs
+, fakechroot
 , fakeroot
 , findutils
 , go
@@ -34,6 +35,10 @@
 }:
 
 let
+  inherit (lib)
+    optionals
+    optionalString
+    ;
 
   inherit (lib)
     escapeShellArgs
@@ -811,6 +816,9 @@ rec {
     , # Optional bash script to run inside fakeroot environment.
       # Could be used for changing ownership of files in customisation layer.
       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.
+      enableFakechroot ? pkgs.stdenv.buildPlatform.isLinux
     , # We pick 100 to ensure there is plenty of room for extension. I
       # believe the actual maximum is 128.
       maxLayers ? 100
@@ -842,16 +850,26 @@ rec {
           name = "${baseName}-customisation-layer";
           paths = contentsList;
           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 = ''
             mv $out old_out
             (cd old_out; eval "$extraCommands" )
 
             mkdir $out
-
-            fakeroot bash -c '
+            ${optionalString enableFakechroot ''
+              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
-              cd old_out
+              ${optionalString (!enableFakechroot) ''cd old_out''}
               eval "$fakeRootCommands"
               tar \
                 --sort name \
diff --git a/pkgs/build-support/docker/examples.nix b/pkgs/build-support/docker/examples.nix
index bef0c584869..28b26be1f8a 100644
--- a/pkgs/build-support/docker/examples.nix
+++ b/pkgs/build-support/docker/examples.nix
@@ -562,6 +562,19 @@ rec {
   # Example export of the bash image
   exportBash = pkgs.dockerTools.exportImage { fromImage = bash; };
 
+  imageViaFakeChroot = pkgs.dockerTools.streamLayeredImage {
+    name = "image-via-fake-chroot";
+    tag = "latest";
+    config.Cmd = [ "hello" ];
+    # 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 {
     name = "build-image-with-path";
     tag = "latest";