Skip to content

Commit

Permalink
Merge pull request #25941 from geoand/#9818
Browse files Browse the repository at this point in the history
Add local project dependencies to a different layer for jib
  • Loading branch information
geoand authored Jun 3, 2022
2 parents c025477 + c4c9a9a commit be9e44c
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 15 deletions.
11 changes: 11 additions & 0 deletions docs/src/main/asciidoc/container-image.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ Other base images might provide launch scripts that enable debugging when an env

Finally, the `quarkus.jib.jvm-entrypoint` configuration property can be used to completely override the container entry point and can thus be used to either hard code the JVM debug configuration or point to a script that handles the details.

==== Multi-module projects and layering

When building a multi-module project containing a Quarkus application as one module and various supporting project dependencies as other modules,
Quarkus supports placing these supporting modules in a separate container image layer from the rest of the application dependencies, with the expectation
that these supporting modules will change more frequently than the regular application dependencies - thus making a rebuild faster if the
application dependencies have not changed.

To enable this feature, the property `quarkus.bootstrap.workspace-discovery` needs to be set to `true` either as a system property
when invoking the build tool, either as a build tool property. Setting this property in `application.properties` will **not** work because
this property needs to be known very early on in the build process.

[#docker]
=== Docker

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,10 @@ private JibContainerBuilder createContainerBuilderFromFastJar(String baseJvmImag
if (artifact == null) {
continue;
}
if (artifact.isWorkspaceModule()) {
fastChangingLibs.add(artifact);
continue;
}
String artifactVersion = artifact.getVersion();
if ((artifactVersion == null) || artifactVersion.isEmpty()) {
continue;
Expand Down Expand Up @@ -430,14 +434,14 @@ private JibContainerBuilder createContainerBuilderFromFastJar(String baseJvmImag
jibConfig.baseRegistryPassword));
if (fastChangingLibPaths.isEmpty()) {
// just create a layer with the entire lib structure intact
jibContainerBuilder.addLayer(Collections.singletonList(componentsPath.resolve(JarResultBuildStep.LIB)),
workDirInContainer);
addLayer(jibContainerBuilder, Collections.singletonList(componentsPath.resolve(JarResultBuildStep.LIB)),
workDirInContainer, "fast-jar-lib");
} 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,
// docker doesn't have to create an entire layer with all dependencies - only change the fast ones

FileEntriesLayer.Builder bootLibsLayerBuilder = FileEntriesLayer.builder();
FileEntriesLayer.Builder bootLibsLayerBuilder = FileEntriesLayer.builder().setName("fast-jar-boot-libs");
Path bootLibPath = componentsPath.resolve(JarResultBuildStep.LIB).resolve(JarResultBuildStep.BOOT_LIB);
try (Stream<Path> boolLibPaths = Files.list(bootLibPath)) {
boolLibPaths.forEach(lib -> {
Expand All @@ -462,7 +466,8 @@ private JibContainerBuilder createContainerBuilderFromFastJar(String baseJvmImag

Path deploymentPath = componentsPath.resolve(JarResultBuildStep.LIB).resolve(JarResultBuildStep.DEPLOYMENT_LIB);
if (Files.exists(deploymentPath)) { // this is the case of mutable-jar
FileEntriesLayer.Builder deploymentLayerBuilder = FileEntriesLayer.builder();
FileEntriesLayer.Builder deploymentLayerBuilder = FileEntriesLayer.builder()
.setName("fast-jar-deployment-libs");
Files.list(deploymentPath).forEach(lib -> {
AbsoluteUnixPath libPathInContainer = workDirInContainer.resolve(JarResultBuildStep.LIB)
.resolve(JarResultBuildStep.DEPLOYMENT_LIB)
Expand All @@ -472,31 +477,30 @@ private JibContainerBuilder createContainerBuilderFromFastJar(String baseJvmImag
jibContainerBuilder.addFileEntriesLayer(deploymentLayerBuilder.build());
}

jibContainerBuilder.addLayer(nonFastChangingLibPaths,
workDirInContainer.resolve(JarResultBuildStep.LIB).resolve(JarResultBuildStep.MAIN));
jibContainerBuilder.addLayer(new ArrayList<>(fastChangingLibPaths),
workDirInContainer.resolve(JarResultBuildStep.LIB).resolve(JarResultBuildStep.MAIN));
AbsoluteUnixPath libsMainPath = workDirInContainer.resolve(JarResultBuildStep.LIB)
.resolve(JarResultBuildStep.MAIN);
addLayer(jibContainerBuilder, nonFastChangingLibPaths, libsMainPath, "fast-jar-normal-libs");
addLayer(jibContainerBuilder, new ArrayList<>(fastChangingLibPaths), libsMainPath, "fast-jar-changing-libs");
}

if (appCDSResult.isPresent()) {
jibContainerBuilder.addFileEntriesLayer(FileEntriesLayer.builder().addEntry(
jibContainerBuilder.addFileEntriesLayer(FileEntriesLayer.builder().setName("app-cds").addEntry(
componentsPath.resolve(JarResultBuildStep.QUARKUS_RUN_JAR),
workDirInContainer.resolve(JarResultBuildStep.QUARKUS_RUN_JAR),
Files.getLastModifiedTime(componentsPath.resolve(JarResultBuildStep.QUARKUS_RUN_JAR)).toInstant())
.build());
jibContainerBuilder
.addLayer(Collections.singletonList(appCDSResult.get().getAppCDS()), workDirInContainer);
} else {
jibContainerBuilder.addFileEntriesLayer(FileEntriesLayer.builder().addEntry(
jibContainerBuilder.addFileEntriesLayer(FileEntriesLayer.builder().setName("fast-jar-run").addEntry(
componentsPath.resolve(JarResultBuildStep.QUARKUS_RUN_JAR),
workDirInContainer.resolve(JarResultBuildStep.QUARKUS_RUN_JAR)).build());
}

jibContainerBuilder
.addLayer(Collections.singletonList(componentsPath.resolve(JarResultBuildStep.APP)),
workDirInContainer)
.addLayer(Collections.singletonList(componentsPath.resolve(JarResultBuildStep.QUARKUS)),
workDirInContainer);
addLayer(jibContainerBuilder, Collections.singletonList(componentsPath.resolve(JarResultBuildStep.APP)),
workDirInContainer, "fast-jar-quarkus-app");
addLayer(jibContainerBuilder, Collections.singletonList(componentsPath.resolve(JarResultBuildStep.QUARKUS)),
workDirInContainer, "fast-jar-quarkus");
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
Expand Down Expand Up @@ -533,6 +537,19 @@ private JibContainerBuilder createContainerBuilderFromFastJar(String baseJvmImag
}
}

public JibContainerBuilder addLayer(JibContainerBuilder jibContainerBuilder, List<Path> files,
AbsoluteUnixPath pathInContainer, String name)
throws IOException {
FileEntriesLayer.Builder layerConfigurationBuilder = FileEntriesLayer.builder().setName(name);

for (Path file : files) {
layerConfigurationBuilder.addEntryRecursive(
file, pathInContainer.resolve(file.getFileName()));
}

return jibContainerBuilder.addFileEntriesLayer(layerConfigurationBuilder.build());
}

private List<String> determineEffectiveJvmArguments(JibConfig jibConfig, Optional<AppCDSResultBuildItem> appCDSResult) {
List<String> effectiveJvmArguments = new ArrayList<>(jibConfig.jvmArguments);
jibConfig.jvmAdditionalArguments.ifPresent(effectiveJvmArguments::addAll);
Expand Down

0 comments on commit be9e44c

Please sign in to comment.