From 4d3fd0bfc51fde337e6d0209c71c200fcbe8de80 Mon Sep 17 00:00:00 2001 From: Florin Botis Date: Thu, 14 Jul 2022 16:58:23 +0200 Subject: [PATCH] Use Instant.EPOCH when adding docker layers Use Instant.EPOCH when adding docker layers so if the content of the files do not change the layer digest doesn't change either --- .../image/jib/deployment/JibConfig.java | 15 +++++++++++++ .../image/jib/deployment/JibProcessor.java | 21 ++++++++++--------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibConfig.java b/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibConfig.java index fdc3129b01c77..ec26ba439f949 100644 --- a/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibConfig.java +++ b/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibConfig.java @@ -217,4 +217,19 @@ public class JibConfig { */ @ConfigItem(defaultValue = "true") public boolean useCurrentTimestamp; + + /** + * Whether to set the modification time (last modified time) of the files put by Jib in the image to the actual + * build time. Otherwise, the modification time will be set to the Unix epoch (00:00:00, January 1st, 1970 in UTC). + * + * If the modification time is constant (flag is set to false so Unix epoch is used) across two consecutive builds, + * the docker layer sha256 digest will be different only if the actual files added by Jib to the docker layer were + * changed. More exactly, having 2 consecutive builds will generate different docker layers only if the actual + * content of the files within the docker layer was changed. + * + * If the current timestamp is used the sha256 digest of the docker layer will always be different even if the + * content of the files didn't change. + */ + @ConfigItem(defaultValue = "true") + public boolean useCurrentTimestampFileModification; } diff --git a/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibProcessor.java b/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibProcessor.java index 3e56a0aea0fd2..98bc4aa5c7708 100644 --- a/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibProcessor.java +++ b/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibProcessor.java @@ -445,6 +445,7 @@ private JibContainerBuilder createContainerBuilderFromFastJar(String baseJvmImag try { Instant now = Instant.now(); + Instant modificationTime = jibConfig.useCurrentTimestampFileModification ? now : Instant.EPOCH; JibContainerBuilder jibContainerBuilder = Jib .from(toRegistryImage(ImageReference.parse(baseJvmImage), jibConfig.baseRegistryUsername, @@ -452,7 +453,7 @@ private JibContainerBuilder createContainerBuilderFromFastJar(String baseJvmImag if (fastChangingLibPaths.isEmpty()) { // just create a layer with the entire lib structure intact addLayer(jibContainerBuilder, Collections.singletonList(componentsPath.resolve(JarResultBuildStep.LIB)), - workDirInContainer, "fast-jar-lib", isMutableJar, now); + workDirInContainer, "fast-jar-lib", isMutableJar, modificationTime); } else { // we need to manually create each layer // the idea here is that the fast changing libraries are created in a later layer, thus when they do change, @@ -486,15 +487,15 @@ private JibContainerBuilder createContainerBuilderFromFastJar(String baseJvmImag .resolve(JarResultBuildStep.DEPLOYMENT_LIB); addLayer(jibContainerBuilder, Collections.singletonList(deploymentPath), workDirInContainer.resolve(JarResultBuildStep.LIB), - "fast-jar-deployment-libs", true, now); + "fast-jar-deployment-libs", true, modificationTime); } AbsoluteUnixPath libsMainPath = workDirInContainer.resolve(JarResultBuildStep.LIB) .resolve(JarResultBuildStep.MAIN); addLayer(jibContainerBuilder, nonFastChangingLibPaths, libsMainPath, "fast-jar-normal-libs", - isMutableJar, now); + isMutableJar, modificationTime); addLayer(jibContainerBuilder, new ArrayList<>(fastChangingLibPaths), libsMainPath, "fast-jar-changing-libs", - isMutableJar, now); + isMutableJar, modificationTime); } if (appCDSResult.isPresent()) { @@ -512,15 +513,15 @@ private JibContainerBuilder createContainerBuilderFromFastJar(String baseJvmImag componentsPath.resolve(JarResultBuildStep.QUARKUS_RUN_JAR), workDirInContainer.resolve(JarResultBuildStep.QUARKUS_RUN_JAR), isMutableJar ? REMOTE_DEV_FILE_PERMISSIONS : DEFAULT_FILE_PERMISSIONS, - now, + modificationTime, isMutableJar ? DEFAULT_BASE_IMAGE_USER : "") .build()); } addLayer(jibContainerBuilder, Collections.singletonList(componentsPath.resolve(JarResultBuildStep.APP)), - workDirInContainer, "fast-jar-quarkus-app", isMutableJar, now); + workDirInContainer, "fast-jar-quarkus-app", isMutableJar, modificationTime); addLayer(jibContainerBuilder, Collections.singletonList(componentsPath.resolve(JarResultBuildStep.QUARKUS)), - workDirInContainer, "fast-jar-quarkus", isMutableJar, now); + workDirInContainer, "fast-jar-quarkus", isMutableJar, modificationTime); if (JibConfig.DEFAULT_WORKING_DIR.equals(jibConfig.workingDirectory)) { // this layer ensures that the working directory is writeable // see https://github.com/GoogleContainerTools/jib/issues/1270 @@ -530,7 +531,7 @@ private JibContainerBuilder createContainerBuilderFromFastJar(String baseJvmImag Files.createTempDirectory("jib"), AbsoluteUnixPath.get(jibConfig.workingDirectory), FilePermissions.DEFAULT_FOLDER_PERMISSIONS, - now, DEFAULT_BASE_IMAGE_USER)) + modificationTime, DEFAULT_BASE_IMAGE_USER)) .build()); } if (isMutableJar) { @@ -541,13 +542,13 @@ private JibContainerBuilder createContainerBuilderFromFastJar(String baseJvmImag Files.createTempDirectory("jib"), workDirInContainer.resolve("dev"), REMOTE_DEV_FOLDER_PERMISSIONS, - now, DEFAULT_BASE_IMAGE_USER)) + modificationTime, DEFAULT_BASE_IMAGE_USER)) .addEntry( new FileEntry( componentsPath.resolve(JarResultBuildStep.QUARKUS_APP_DEPS), workDirInContainer.resolve(JarResultBuildStep.QUARKUS_APP_DEPS), REMOTE_DEV_FOLDER_PERMISSIONS, - now, DEFAULT_BASE_IMAGE_USER)) + modificationTime, DEFAULT_BASE_IMAGE_USER)) .build()); }