dockerTools: Allow separately specifying metadata and filesystem timestamps (#327579)
This commit is contained in:
@@ -453,7 +453,7 @@ See [](#ex-dockerTools-streamLayeredImage-exploringlayers) to understand how the
|
||||
`streamLayeredImage` allows scripts to be run when creating the additional layer with symlinks, allowing custom behaviour to affect the final results of the image (see the documentation of the `extraCommands` and `fakeRootCommands` attributes).
|
||||
|
||||
The resulting repository tarball will list a single image as specified by the `name` and `tag` attributes.
|
||||
By default, that image will use a static creation date (see documentation for the `created` attribute).
|
||||
By default, that image will use a static creation date (see documentation for the `created` and `mtime` attributes).
|
||||
This allows the function to produce reproducible images.
|
||||
|
||||
### Inputs {#ssec-pkgs-dockerTools-streamLayeredImage-inputs}
|
||||
@@ -516,6 +516,7 @@ This allows the function to produce reproducible images.
|
||||
`created` (String; _optional_)
|
||||
|
||||
: Specifies the time of creation of the generated image.
|
||||
This date will be used for the image metadata.
|
||||
This should be either a date and time formatted according to [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) or `"now"`, in which case the current date will be used.
|
||||
|
||||
:::{.caution}
|
||||
@@ -524,6 +525,18 @@ This allows the function to produce reproducible images.
|
||||
|
||||
_Default value:_ `"1970-01-01T00:00:01Z"`.
|
||||
|
||||
`mtime` (String; _optional_)
|
||||
|
||||
: Specifies the time used for the modification timestamp of files within the layers of the generated image.
|
||||
This should be either a date and time formatted according to [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) or `"now"`, in which case the current date will be used.
|
||||
|
||||
:::{.caution}
|
||||
Using a non-constant date will cause built layers to have a different hash each time, preventing deduplication.
|
||||
Using `"now"` also means that the generated image will not be reproducible anymore (because the date will always change whenever it's built).
|
||||
:::
|
||||
|
||||
_Default value:_ `"1970-01-01T00:00:01Z"`.
|
||||
|
||||
`uid` (Number; _optional_) []{#dockerTools-buildLayeredImage-arg-uid}
|
||||
`gid` (Number; _optional_) []{#dockerTools-buildLayeredImage-arg-gid}
|
||||
`uname` (String; _optional_) []{#dockerTools-buildLayeredImage-arg-uname}
|
||||
|
||||
@@ -907,6 +907,7 @@ rec {
|
||||
, config ? { }
|
||||
, architecture ? defaultArchitecture
|
||||
, created ? "1970-01-01T00:00:01Z"
|
||||
, mtime ? "1970-01-01T00:00:01Z"
|
||||
, uid ? 0
|
||||
, gid ? 0
|
||||
, uname ? "root"
|
||||
@@ -1009,7 +1010,7 @@ rec {
|
||||
|
||||
conf = runCommand "${baseName}-conf.json"
|
||||
{
|
||||
inherit fromImage maxLayers created uid gid uname gname;
|
||||
inherit fromImage maxLayers created mtime uid gid uname gname;
|
||||
imageName = lib.toLower name;
|
||||
preferLocalBuild = true;
|
||||
passthru.imageTag =
|
||||
@@ -1029,10 +1030,13 @@ rec {
|
||||
imageTag="${tag}"
|
||||
''}
|
||||
|
||||
# convert "created" to iso format
|
||||
# convert "created" and "mtime" to iso format
|
||||
if [[ "$created" != "now" ]]; then
|
||||
created="$(date -Iseconds -d "$created")"
|
||||
fi
|
||||
if [[ "$mtime" != "now" ]]; then
|
||||
mtime="$(date -Iseconds -d "$mtime")"
|
||||
fi
|
||||
|
||||
paths() {
|
||||
cat $paths ${lib.concatMapStringsSep " "
|
||||
@@ -1089,6 +1093,7 @@ rec {
|
||||
"customisation_layer", $customisation_layer,
|
||||
"repo_tag": $repo_tag,
|
||||
"created": $created,
|
||||
"mtime": $mtime,
|
||||
"uid": $uid,
|
||||
"gid": $gid,
|
||||
"uname": $uname,
|
||||
@@ -1100,6 +1105,7 @@ rec {
|
||||
--arg customisation_layer ${customisationLayer} \
|
||||
--arg repo_tag "$imageName:$imageTag" \
|
||||
--arg created "$created" \
|
||||
--arg mtime "$mtime" \
|
||||
--arg uid "$uid" \
|
||||
--arg gid "$gid" \
|
||||
--arg uname "$uname" \
|
||||
|
||||
@@ -307,6 +307,15 @@ def add_bytes(tar, path, content, mtime):
|
||||
tar.addfile(ti, io.BytesIO(content))
|
||||
|
||||
|
||||
now = datetime.now(tz=timezone.utc)
|
||||
|
||||
|
||||
def parse_time(s):
|
||||
if s == "now":
|
||||
return now
|
||||
return datetime.fromisoformat(s)
|
||||
|
||||
|
||||
def main():
|
||||
arg_parser = argparse.ArgumentParser(
|
||||
description="""
|
||||
@@ -342,12 +351,8 @@ Docker Image Specification v1.2 as reference [1].
|
||||
with open(args.conf, "r") as f:
|
||||
conf = json.load(f)
|
||||
|
||||
created = (
|
||||
datetime.now(tz=timezone.utc)
|
||||
if conf["created"] == "now"
|
||||
else datetime.fromisoformat(conf["created"])
|
||||
)
|
||||
mtime = int(created.timestamp())
|
||||
created = parse_time(conf["created"])
|
||||
mtime = int(parse_time(conf["mtime"]).timestamp())
|
||||
uid = int(conf["uid"])
|
||||
gid = int(conf["gid"])
|
||||
uname = conf["uname"]
|
||||
|
||||
Reference in New Issue
Block a user