summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/tests/docker-tools.nix17
-rw-r--r--pkgs/build-support/docker/default.nix9
-rw-r--r--pkgs/build-support/docker/examples.nix22
3 files changed, 44 insertions, 4 deletions
diff --git a/nixos/tests/docker-tools.nix b/nixos/tests/docker-tools.nix
index 54dd97e5b13..51b472fcf9c 100644
--- a/nixos/tests/docker-tools.nix
+++ b/nixos/tests/docker-tools.nix
@@ -137,5 +137,22 @@ import ./make-test-python.nix ({ pkgs, ... }: {
             # Ensure the two output paths (ls and hello) are in the layer
             "docker run bulk-layer ls /bin/hello",
         )
+
+    with subtest("Ensure correct behavior when no store is needed"):
+        # This check tests two requirements simultaneously
+        #  1. buildLayeredImage can build images that don't need a store.
+        #  2. Layers of symlinks are eliminated by the customization layer.
+        #
+        docker.succeed(
+            "docker load --input='${pkgs.dockerTools.examples.no-store-paths}'"
+        )
+
+        # Busybox will not recognize argv[0] and print an error message with argv[0],
+        # but it confirms that the custom-true symlink is present.
+        docker.succeed("docker run --rm no-store-paths custom-true |& grep custom-true")
+
+        # This check may be loosened to allow an *empty* store rather than *no* store.
+        docker.succeed("docker run --rm no-store-paths ls /")
+        docker.fail("docker run --rm no-store-paths ls /nix/store")
   '';
 })
diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix
index ff9949bc8dd..28c0d2dfcae 100644
--- a/pkgs/build-support/docker/default.nix
+++ b/pkgs/build-support/docker/default.nix
@@ -319,6 +319,8 @@ rec {
       enableParallelBuilding = true;
     }
     ''
+      mkdir layers
+
       # Delete impurities for store path layers, so they don't get
       # shared and taint other projects.
       cat ${configJson} \
@@ -330,13 +332,12 @@ rec {
       # created, and that no paths are missed. If you change the
       # following head and tail call lines, double-check that your
       # code behaves properly when the number of layers equals:
-      #      maxLayers-1, maxLayers, and maxLayers+1
+      #      maxLayers-1, maxLayers, and maxLayers+1, 0
       paths() {
-        cat $paths ${lib.concatMapStringsSep " " (path: "| grep -v ${path}") (closures ++ [ overallClosure ])}
+        cat $paths ${lib.concatMapStringsSep " " (path: "| (grep -v ${path} || true)") (closures ++ [ overallClosure ])}
       }
 
-      # We need to sponge to avoid grep broken pipe error when maxLayers == 1
-      paths | sponge | head -n $((maxLayers - 1)) | cat -n | xargs -r -P$NIX_BUILD_CORES -n2 ${storePathToLayer}
+      paths | head -n $((maxLayers - 1)) | cat -n | xargs -r -P$NIX_BUILD_CORES -n2 ${storePathToLayer}
       if [ $(paths | wc -l) -ge $maxLayers ]; then
         paths | tail -n+$maxLayers | xargs ${storePathToLayer} $maxLayers
       fi
diff --git a/pkgs/build-support/docker/examples.nix b/pkgs/build-support/docker/examples.nix
index f0dcf236c0e..f42b35e6494 100644
--- a/pkgs/build-support/docker/examples.nix
+++ b/pkgs/build-support/docker/examples.nix
@@ -258,4 +258,26 @@ rec {
     maxLayers = 2;
   };
 
+  # 17. Create a "layered" image without nix store layers. This is not
+  # recommended, but can be useful for base images in rare cases.
+  no-store-paths = pkgs.dockerTools.buildLayeredImage {
+    name = "no-store-paths";
+    tag = "latest";
+    extraCommands = ''
+      chmod a+w bin
+
+      # This removes sharing of busybox and is not recommended. We do this
+      # to make the example suitable as a test case with working binaries.
+      cp -r ${pkgs.pkgsStatic.busybox}/* .
+    '';
+    contents = [
+      # This layer has no dependencies and its symlinks will be dereferenced
+      # when creating the customization layer.
+      (pkgs.runCommand "layer-to-flatten" {} ''
+        mkdir -p $out/bin
+        ln -s /bin/true $out/bin/custom-true
+      ''
+      )
+    ];
+  };
 }