Skip to content

Commit

Permalink
Change the default base images from Distroless in Jib build plugins (#…
Browse files Browse the repository at this point in the history
…3124)

* Change base image from Distroless to AdoptOpenJDK
* Remove extra layer hack
* Deprecate distroless methods
* Update Javadocs
  • Loading branch information
chanseokoh authored Apr 5, 2021
1 parent f49f85e commit f20cfcd
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
/**
* Exception when the Java version in the base image is incompatible with the Java version of the
* application to be containerized. For example, when the project is Java 11 but the base image is
* {@code gcr.io/distroless/java:8}.
* {@code adoptopenjdk:8-jre}.
*/
public class IncompatibleBaseImageJavaVersionException extends Exception {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ public static JibContainerBuilder fromExplodedWar(
javaContainerBuilder.addClasses(webInfClasses, isClassFile);
}
if (Files.exists(webInfLib)) {

javaContainerBuilder.addDependencies(
new DirectoryWalker(webInfLib)
.filterRoot()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
Expand Down Expand Up @@ -84,7 +85,7 @@ public class PluginConfigurationProcessor {
private static final ImmutableList<String> CONST_LAYERS =
ImmutableList.of(LayerType.DEPENDENCIES.getName());

private static final String DEFAULT_JETTY_APP_ROOT = "/jetty/webapps/ROOT";
private static final String DEFAULT_JETTY_APP_ROOT = "/var/lib/jetty/webapps/ROOT";

/**
* Generate a runner for image builds to docker daemon.
Expand Down Expand Up @@ -502,10 +503,10 @@ static JavaContainerBuilder getJavaContainerBuilderWithBaseImage(
// Verify Java version is compatible
String prefixRemoved = baseImageConfig.replaceFirst(".*://", "");
int javaVersion = projectProperties.getMajorJavaVersion();
if (isKnownDistrolessJava8Image(prefixRemoved) && javaVersion > 8) {
if (isKnownJava8Image(prefixRemoved) && javaVersion > 8) {
throw new IncompatibleBaseImageJavaVersionException(8, javaVersion);
}
if (isKnownDistrolessJava11Image(prefixRemoved) && javaVersion > 11) {
if (isKnownJava11Image(prefixRemoved) && javaVersion > 11) {
throw new IncompatibleBaseImageJavaVersionException(11, javaVersion);
}

Expand Down Expand Up @@ -542,7 +543,7 @@ static JavaContainerBuilder getJavaContainerBuilderWithBaseImage(
* <ol>
* <li>null (inheriting from the base image), if the user specified value is {@code INHERIT}
* <li>the user specified one, if set
* <li>for a WAR project, null (it must be inherited from base image)
* <li>for a WAR project, {@code ["java", "-jar", "/usr/local/jetty/start.jar"]}
* <li>for a non-WAR project, by resolving the main class
* </ol>
*
Expand Down Expand Up @@ -588,7 +589,7 @@ static List<String> computeEntrypoint(
"mainClass, extraClasspath, jvmFlags, and expandClasspathDependencies "
+ "are ignored for WAR projects"));
}
return null;
return Arrays.asList("java", "-jar", "/usr/local/jetty/start.jar");
}

List<String> classpath = new ArrayList<>(rawExtraClasspath);
Expand Down Expand Up @@ -634,8 +635,8 @@ static List<String> computeEntrypoint(

/**
* Gets the suitable value for the base image. If the raw base image parameter is null, returns
* {@code "gcr.io/distroless/java/jetty"} for WAR projects or {@code "gcr.io/distroless/java"} for
* non-WAR.
* {@code "jetty"} for WAR projects or {@code "adoptopenjdk:8-jre"} or {@code
* "adoptopenjdk:11-jre"} for non-WAR.
*
* @param projectProperties used for providing additional information
* @return the base image
Expand All @@ -645,16 +646,14 @@ static List<String> computeEntrypoint(
@VisibleForTesting
static String getDefaultBaseImage(ProjectProperties projectProperties)
throws IncompatibleBaseImageJavaVersionException {
if (projectProperties.isWarProject()) {
return "jetty";
}
int javaVersion = projectProperties.getMajorJavaVersion();
if (javaVersion <= 8) {
return projectProperties.isWarProject()
? "gcr.io/distroless/java/jetty:java8"
: "gcr.io/distroless/java:8";
}
if (javaVersion <= 11) {
return projectProperties.isWarProject()
? "gcr.io/distroless/java/jetty:java11"
: "gcr.io/distroless/java:11";
return "adoptopenjdk:8-jre";
} else if (javaVersion <= 11) {
return "adoptopenjdk:11-jre";
}
throw new IncompatibleBaseImageJavaVersionException(11, javaVersion);
}
Expand Down Expand Up @@ -721,8 +720,8 @@ static Set<AbsoluteUnixPath> getVolumesSet(RawConfiguration rawConfiguration)

/**
* Gets the value of the {@code appRoot} parameter. If the parameter is empty, returns {@code
* /jetty/webapps/ROOT} for WAR projects or {@link JavaContainerBuilder#DEFAULT_APP_ROOT} for
* other projects.
* /var/lib/jetty/webapps/ROOT} for WAR projects or {@link JavaContainerBuilder#DEFAULT_APP_ROOT}
* for other projects.
*
* @param rawConfiguration raw configuration data
* @param projectProperties the project properties
Expand Down Expand Up @@ -952,40 +951,22 @@ private static Path getCheckedCacheDirectory(String property, Path defaultPath)
}

/**
* Checks if the given image is a known Java 8 distroless image. Checking against only images
* known to Java 8, the method may to return {@code false} for Java 8 distroless unknown to it.
* Checks if the given image is a known Java 8 image. May return false negative.
*
* @param imageReference the image reference
* @return {@code true} if the image is equal to one of the known Java 8 distroless images, else
* {@code false}
* @return {@code true} if the image is a known Java 8 image
*/
private static boolean isKnownDistrolessJava8Image(String imageReference) {
// TODO: drop "latest", "debug", and the like once they no longer point to Java 8.
return imageReference.equals("gcr.io/distroless/java")
|| imageReference.equals("gcr.io/distroless/java:latest")
|| imageReference.equals("gcr.io/distroless/java:debug")
|| imageReference.equals("gcr.io/distroless/java:8")
|| imageReference.equals("gcr.io/distroless/java:8-debug")
|| imageReference.equals("gcr.io/distroless/java/jetty")
|| imageReference.equals("gcr.io/distroless/java/jetty:latest")
|| imageReference.equals("gcr.io/distroless/java/jetty:debug")
|| imageReference.equals("gcr.io/distroless/java/jetty:java8")
|| imageReference.equals("gcr.io/distroless/java/jetty:java8-debug");
private static boolean isKnownJava8Image(String imageReference) {
return imageReference.startsWith("adoptopenjdk:8");
}

/**
* Checks if the given image is a known Java 11 distroless image. Checking against only images
* known to Java 11, the method may to return {@code false} for Java 11 distroless unknown to it.
* Checks if the given image is a known Java 11 image. May return false negative.
*
* @param imageReference the image reference
* @return {@code true} if the image is equal to one of the known Java 11 distroless images, else
* {@code false}
* @return {@code true} if the image is a known Java 11 image
*/
private static boolean isKnownDistrolessJava11Image(String imageReference) {
// TODO: add "latest", "debug", and the like to this list once they point to Java 11.
return imageReference.equals("gcr.io/distroless/java:11")
|| imageReference.equals("gcr.io/distroless/java:11-debug")
|| imageReference.equals("gcr.io/distroless/java/jetty:java11")
|| imageReference.equals("gcr.io/distroless/java/jetty:java11-debug");
private static boolean isKnownJava11Image(String imageReference) {
return imageReference.startsWith("adoptopenjdk:11");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,9 @@ public void testEntrypoint_defaultWarPackaging()

BuildContext buildContext = getBuildContext(processCommonConfiguration());

assertThat(buildContext.getContainerConfiguration().getEntrypoint()).isNull();
assertThat(buildContext.getContainerConfiguration().getEntrypoint())
.containsExactly("java", "-jar", "/usr/local/jetty/start.jar")
.inOrder();
verifyNoInteractions(logger);
}

Expand Down Expand Up @@ -516,7 +518,9 @@ public void testEntrypoint_warningOnMainclassForWar()

BuildContext buildContext = getBuildContext(processCommonConfiguration());

assertThat(buildContext.getContainerConfiguration().getEntrypoint()).isNull();
assertThat(buildContext.getContainerConfiguration().getEntrypoint())
.containsExactly("java", "-jar", "/usr/local/jetty/start.jar")
.inOrder();
verify(projectProperties)
.log(
LogEvent.warn(
Expand All @@ -536,7 +540,9 @@ public void testEntrypoint_warningOnExpandClasspathDependenciesForWar()

BuildContext buildContext = getBuildContext(processCommonConfiguration());

assertThat(buildContext.getContainerConfiguration().getEntrypoint()).isNull();
assertThat(buildContext.getContainerConfiguration().getEntrypoint())
.containsExactly("java", "-jar", "/usr/local/jetty/start.jar")
.inOrder();
verify(projectProperties)
.log(
LogEvent.warn(
Expand All @@ -562,21 +568,6 @@ public void testEntrypointClasspath_nonDefaultAppRoot()
.inOrder();
}

@Test
public void testWebAppEntrypoint_inheritedFromBaseImage()
throws InvalidImageReferenceException, IOException, CacheDirectoryCreationException,
MainClassInferenceException, InvalidAppRootException, InvalidWorkingDirectoryException,
InvalidPlatformException, InvalidContainerVolumeException,
IncompatibleBaseImageJavaVersionException, NumberFormatException,
InvalidContainerizingModeException, InvalidFilesModificationTimeException,
InvalidCreationTimeException {
when(projectProperties.isWarProject()).thenReturn(true);

BuildContext buildContext = getBuildContext(processCommonConfiguration());

assertThat(buildContext.getContainerConfiguration().getEntrypoint()).isNull();
}

@Test
public void testGetAppRootChecked() throws InvalidAppRootException {
when(rawConfiguration.getAppRoot()).thenReturn("/some/root");
Expand Down Expand Up @@ -639,7 +630,7 @@ public void testGetAppRootChecked_defaultWarProject() throws InvalidAppRootExcep
when(projectProperties.isWarProject()).thenReturn(true);

assertThat(PluginConfigurationProcessor.getAppRootChecked(rawConfiguration, projectProperties))
.isEqualTo(AbsoluteUnixPath.get("/jetty/webapps/ROOT"));
.isEqualTo(AbsoluteUnixPath.get("/var/lib/jetty/webapps/ROOT"));
}

@Test
Expand Down Expand Up @@ -691,7 +682,7 @@ public void testGetDefaultBaseImage_nonWarPackaging()
when(projectProperties.isWarProject()).thenReturn(false);

assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:8");
.isEqualTo("adoptopenjdk:8-jre");
}

@Test
Expand All @@ -700,73 +691,39 @@ public void testGetDefaultBaseImage_warProject()
when(projectProperties.isWarProject()).thenReturn(true);

assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java8");
}

@Test
public void testGetDefaultBaseImage_chooseJava8Distroless()
throws IncompatibleBaseImageJavaVersionException {
when(projectProperties.getMajorJavaVersion()).thenReturn(6);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:8");

when(projectProperties.getMajorJavaVersion()).thenReturn(7);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:8");

when(projectProperties.getMajorJavaVersion()).thenReturn(8);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:8");
}

@Test
public void testGetDefaultBaseImage_chooseJava11Distroless()
throws IncompatibleBaseImageJavaVersionException {
when(projectProperties.getMajorJavaVersion()).thenReturn(9);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:11");

when(projectProperties.getMajorJavaVersion()).thenReturn(10);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:11");

when(projectProperties.getMajorJavaVersion()).thenReturn(11);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:11");
.isEqualTo("jetty");
}

@Test
public void testGetDefaultBaseImage_chooseJava8JettyDistroless()
public void testGetDefaultBaseImage_chooseJava8BaseImage()
throws IncompatibleBaseImageJavaVersionException {
when(projectProperties.getMajorJavaVersion()).thenReturn(6);
when(projectProperties.isWarProject()).thenReturn(true);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java8");
.isEqualTo("adoptopenjdk:8-jre");

when(projectProperties.getMajorJavaVersion()).thenReturn(7);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java8");
.isEqualTo("adoptopenjdk:8-jre");

when(projectProperties.getMajorJavaVersion()).thenReturn(8);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java8");
.isEqualTo("adoptopenjdk:8-jre");
}

@Test
public void testGetDefaultBaseImage_chooseJava11JettyDistroless()
public void testGetDefaultBaseImage_chooseJava11BaseImage()
throws IncompatibleBaseImageJavaVersionException {
when(projectProperties.getMajorJavaVersion()).thenReturn(9);
when(projectProperties.isWarProject()).thenReturn(true);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java11");
.isEqualTo("adoptopenjdk:11-jre");

when(projectProperties.getMajorJavaVersion()).thenReturn(10);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java11");
.isEqualTo("adoptopenjdk:11-jre");

when(projectProperties.getMajorJavaVersion()).thenReturn(11);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java11");
.isEqualTo("adoptopenjdk:11-jre");
}

@Test
Expand Down Expand Up @@ -829,7 +786,7 @@ public void testGetJavaContainerBuilderWithBaseImage_registryWithPrefix()
public void testGetJavaContainerBuilderWithBaseImage_incompatibleJava8BaseImage() {
when(projectProperties.getMajorJavaVersion()).thenReturn(11);

when(rawConfiguration.getFromImage()).thenReturn(Optional.of("gcr.io/distroless/java:8"));
when(rawConfiguration.getFromImage()).thenReturn(Optional.of("adoptopenjdk:8"));
IncompatibleBaseImageJavaVersionException exception1 =
assertThrows(
IncompatibleBaseImageJavaVersionException.class,
Expand All @@ -839,7 +796,7 @@ public void testGetJavaContainerBuilderWithBaseImage_incompatibleJava8BaseImage(
assertThat(exception1.getBaseImageMajorJavaVersion()).isEqualTo(8);
assertThat(exception1.getProjectMajorJavaVersion()).isEqualTo(11);

when(rawConfiguration.getFromImage()).thenReturn(Optional.of("gcr.io/distroless/java:latest"));
when(rawConfiguration.getFromImage()).thenReturn(Optional.of("adoptopenjdk:8-jre"));
IncompatibleBaseImageJavaVersionException exception2 =
assertThrows(
IncompatibleBaseImageJavaVersionException.class,
Expand All @@ -854,47 +811,25 @@ public void testGetJavaContainerBuilderWithBaseImage_incompatibleJava8BaseImage(
public void testGetJavaContainerBuilderWithBaseImage_incompatibleJava11BaseImage() {
when(projectProperties.getMajorJavaVersion()).thenReturn(15);

when(rawConfiguration.getFromImage()).thenReturn(Optional.of("gcr.io/distroless/java:11"));
IncompatibleBaseImageJavaVersionException exception =
assertThrows(
IncompatibleBaseImageJavaVersionException.class,
() ->
PluginConfigurationProcessor.getJavaContainerBuilderWithBaseImage(
rawConfiguration, projectProperties, inferredAuthProvider));
assertThat(exception.getBaseImageMajorJavaVersion()).isEqualTo(11);
assertThat(exception.getProjectMajorJavaVersion()).isEqualTo(15);
}

@Test
public void testGetJavaContainerBuilderWithBaseImage_incompatibleJava8JettyBaseImage() {
when(projectProperties.getMajorJavaVersion()).thenReturn(11);

when(rawConfiguration.getFromImage())
.thenReturn(Optional.of("gcr.io/distroless/java/jetty:java8"));
IncompatibleBaseImageJavaVersionException exception =
when(rawConfiguration.getFromImage()).thenReturn(Optional.of("adoptopenjdk:11"));
IncompatibleBaseImageJavaVersionException exception1 =
assertThrows(
IncompatibleBaseImageJavaVersionException.class,
() ->
PluginConfigurationProcessor.getJavaContainerBuilderWithBaseImage(
rawConfiguration, projectProperties, inferredAuthProvider));
assertThat(exception.getBaseImageMajorJavaVersion()).isEqualTo(8);
assertThat(exception.getProjectMajorJavaVersion()).isEqualTo(11);
}

@Test
public void testGetJavaContainerBuilderWithBaseImage_incompatibleJava11JettyBaseImage() {
when(projectProperties.getMajorJavaVersion()).thenReturn(15);
assertThat(exception1.getBaseImageMajorJavaVersion()).isEqualTo(11);
assertThat(exception1.getProjectMajorJavaVersion()).isEqualTo(15);

when(rawConfiguration.getFromImage())
.thenReturn(Optional.of("gcr.io/distroless/java/jetty:java11"));
IncompatibleBaseImageJavaVersionException exception =
when(rawConfiguration.getFromImage()).thenReturn(Optional.of("adoptopenjdk:11-jre"));
IncompatibleBaseImageJavaVersionException exception2 =
assertThrows(
IncompatibleBaseImageJavaVersionException.class,
() ->
PluginConfigurationProcessor.getJavaContainerBuilderWithBaseImage(
rawConfiguration, projectProperties, inferredAuthProvider));
assertThat(exception.getBaseImageMajorJavaVersion()).isEqualTo(11);
assertThat(exception.getProjectMajorJavaVersion()).isEqualTo(15);
assertThat(exception2.getBaseImageMajorJavaVersion()).isEqualTo(11);
assertThat(exception2.getProjectMajorJavaVersion()).isEqualTo(15);
}

// https://github.com/GoogleContainerTools/jib/issues/1995
Expand Down

0 comments on commit f20cfcd

Please sign in to comment.