summary refs log tree commit diff
diff options
context:
space:
mode:
authorGraham Christensen <graham.christensen@target.com>2018-09-20 11:40:36 -0400
committerRobin Gloster <mail@glob.in>2018-09-20 18:26:02 +0200
commita32d7e0c74465e685c997624b12d1582fda05fd9 (patch)
tree1bb5ddff773eb6018081132bbcf168df0f1028d5
parentb0987f201337042af2a414549e1948e82d994290 (diff)
downloadnixpkgs-a32d7e0c74465e685c997624b12d1582fda05fd9.tar
nixpkgs-a32d7e0c74465e685c997624b12d1582fda05fd9.tar.gz
nixpkgs-a32d7e0c74465e685c997624b12d1582fda05fd9.tar.bz2
nixpkgs-a32d7e0c74465e685c997624b12d1582fda05fd9.tar.lz
nixpkgs-a32d7e0c74465e685c997624b12d1582fda05fd9.tar.xz
nixpkgs-a32d7e0c74465e685c997624b12d1582fda05fd9.tar.zst
nixpkgs-a32d7e0c74465e685c997624b12d1582fda05fd9.zip
dockerTools.buildImage: support impure dates
Because dates are an impurity, by default buildImage will use a static
date of one second past the UNIX Epoch. This can be a bit frustrating
when listing docker images in the CLI:

    $ docker image list
    REPOSITORY   TAG      IMAGE ID       CREATED        SIZE
    hello        latest   08c791c7846e   48 years ago   25.2MB

If you want to trade the purity for a better user experience, you can
set created to now.

    pkgs.dockerTools.buildImage {
      name = "hello";
      tag = "latest";
      created = "now";
      contents = pkgs.hello;

      config.Cmd = [ "/bin/hello" ];
    }

and now the Docker CLI will display a reasonable date and sort the
images as expected:

    $ docker image list
    REPOSITORY   TAG      IMAGE ID       CREATED              SIZE
    hello        latest   de2bf4786de6   About a minute ago   25.2MB
-rw-r--r--doc/functions.xml39
-rw-r--r--pkgs/build-support/docker/default.nix19
2 files changed, 52 insertions, 6 deletions
diff --git a/doc/functions.xml b/doc/functions.xml
index 3cfc6884bd2..31b40fb084a 100644
--- a/doc/functions.xml
+++ b/doc/functions.xml
@@ -638,6 +638,45 @@ buildImage {
      <literal>pkgs.cacert</literal> to <varname>contents</varname>.
     </para>
    </note>
+
+   <example xml:id="example-pkgs-dockerTools-buildImage-creation-date">
+     <title>Impurely Defining a Docker Layer's Creation Date</title>
+     <para>
+       Because dates are an impurity, by default
+       <function>buildImage</function> will use a static date of one
+       second past the UNIX Epoch. This can be a bit frustrating when
+       listing docker images in the CLI:
+     </para>
+     <screen><![CDATA[
+$ docker image list
+REPOSITORY   TAG      IMAGE ID       CREATED        SIZE
+hello        latest   08c791c7846e   48 years ago   25.2MB
+]]></screen>
+     <para>
+       If you want to trade the purity for a better user experience,
+       you can set <literal>created</literal> to
+       <literal>now</literal>.
+     </para>
+     <programlisting><![CDATA[
+pkgs.dockerTools.buildImage {
+  name = "hello";
+  tag = "latest";
+  created = "now";
+  contents = pkgs.hello;
+
+  config.Cmd = [ "/bin/hello" ];
+}
+]]></programlisting>
+     <para>
+       and now the Docker CLI will display a reasonable date and
+       sort the images as expected:
+     </para>
+     <screen><![CDATA[
+$ docker image list
+REPOSITORY   TAG      IMAGE ID       CREATED              SIZE
+hello        latest   de2bf4786de6   About a minute ago   25.2MB
+]]></screen>
+   </example>
   </section>
 
   <section xml:id="ssec-pkgs-dockerTools-fetchFromRegistry">
diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix
index 93b715659eb..0cee1dd2916 100644
--- a/pkgs/build-support/docker/default.nix
+++ b/pkgs/build-support/docker/default.nix
@@ -450,11 +450,18 @@ rec {
       baseName = baseNameOf name;
 
       # Create a JSON blob of the configuration. Set the date to unix zero.
-      baseJson = writeText "${baseName}-config.json" (builtins.toJSON {
-        inherit created config;
-        architecture = "amd64";
-        os = "linux";
-      });
+      baseJson = let
+          pure = writeText "${baseName}-config.json" (builtins.toJSON {
+            inherit created config;
+            architecture = "amd64";
+            os = "linux";
+          });
+          impure = runCommand "${baseName}-config.json"
+            { buildInputs = [ jq ]; }
+            ''
+               jq ".created = \"$(TZ=utc date --iso-8601="seconds")\"" ${pure} > $out
+            '';
+        in if created == "now" then impure else pure;
 
       layer =
         if runAsRoot == null
@@ -577,7 +584,7 @@ rec {
         currentID=$layerID
         while [[ -n "$currentID" ]]; do
           layerChecksum=$(sha256sum image/$currentID/layer.tar | cut -d ' ' -f1)
-          imageJson=$(echo "$imageJson" | jq ".history |= [{\"created\": \"${created}\"}] + .")
+          imageJson=$(echo "$imageJson" | jq ".history |= [{\"created\": \"$(jq -r .created ${baseJson})\"}] + .")
           imageJson=$(echo "$imageJson" | jq ".rootfs.diff_ids |= [\"sha256:$layerChecksum\"] + .")
           manifestJson=$(echo "$manifestJson" | jq ".[0].Layers |= [\"$currentID/layer.tar\"] + .")