Introduce jib extension as an alternative for building container images and harmonize code between it and the docker extension

This commit is contained in:
Georgios Andrianakis
2020-02-10 10:13:45 +02:00
parent c38782a5c1
commit a08ad6bef8
46 changed files with 940 additions and 178 deletions

View File

@@ -473,12 +473,22 @@
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-deployment</artifactId>
<artifactId>quarkus-container-image-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-spi</artifactId>
<artifactId>quarkus-container-image-spi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-docker-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-jib-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>

View File

@@ -185,6 +185,8 @@
<jzlib.version>1.1.1</jzlib.version>
<checker-qual.version>2.5.2</checker-qual.version>
<error-prone-annotations.version>2.2.0</error-prone-annotations.version>
<jib-core.version>0.13.0</jib-core.version>
<google-http-client.version>1.34.0</google-http-client.version>
</properties>
<dependencyManagement>
@@ -713,7 +715,12 @@
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container</artifactId>
<artifactId>quarkus-container-image-docker</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-jib</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
@@ -2857,6 +2864,24 @@
<artifactId>quarkus-banner</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Jib -->
<dependency>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-core</artifactId>
<version>${jib-core.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client</artifactId>
<version>${google-http-client.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-docker-parent</artifactId>
<version>999-SNAPSHOT</version>
</parent>
<artifactId>quarkus-container-image-docker-deployment</artifactId>
<name>Quarkus - Container - Image - Docker - Deployment</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-docker</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-deployment</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,5 +1,5 @@
package io.quarkus.container.deployment;
package io.quarkus.container.image.docker.deployment;
import java.io.BufferedReader;
import java.io.File;
@@ -11,6 +11,7 @@ import java.util.function.Function;
import org.jboss.logging.Logger;
import io.quarkus.container.image.deployment.ContainerImageConfig;
import io.quarkus.deployment.util.ExecUtil;
public class DockerBuild implements BooleanSupplier {
@@ -18,15 +19,15 @@ public class DockerBuild implements BooleanSupplier {
private static final Logger LOGGER = Logger.getLogger(DockerBuild.class.getName());
private static boolean daemonFound = false;
private final ContainerConfig containerConfig;
private final ContainerImageConfig containerImageConfig;
DockerBuild(ContainerConfig containerConfig) {
this.containerConfig = containerConfig;
public DockerBuild(ContainerImageConfig containerImageConfig) {
this.containerImageConfig = containerImageConfig;
}
@Override
public boolean getAsBoolean() {
if (containerConfig.build) {
if (containerImageConfig.execution != ContainerImageConfig.Execution.NONE) {
//No need to perform the check multiple times.
if (daemonFound) {
return true;

View File

@@ -1,5 +1,5 @@
package io.quarkus.container.deployment;
package io.quarkus.container.image.docker.deployment;
import java.io.BufferedReader;
import java.io.IOException;
@@ -11,20 +11,19 @@ import java.nio.file.Paths;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import javax.inject.Inject;
import org.jboss.logging.Logger;
import io.quarkus.container.deployment.util.ImageUtil;
import io.quarkus.container.image.deployment.ContainerImageConfig;
import io.quarkus.container.image.deployment.util.ImageUtil;
import io.quarkus.container.image.deployment.util.NativeBinaryUtil;
import io.quarkus.container.spi.ContainerImageBuildItem;
import io.quarkus.container.spi.ContainerImageResultBuildItem;
import io.quarkus.deployment.IsNormal;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
import io.quarkus.deployment.pkg.builditem.ArtifactResultBuildItem;
import io.quarkus.deployment.pkg.builditem.JarBuildItem;
import io.quarkus.deployment.pkg.builditem.NativeImageBuildItem;
@@ -32,51 +31,85 @@ import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
import io.quarkus.deployment.pkg.steps.NativeBuild;
import io.quarkus.deployment.util.ExecUtil;
public class DockerBuildStep {
public class DockerProcessor {
private static final Logger log = Logger.getLogger(DockerBuildStep.class);
private static final Logger log = Logger.getLogger(DockerProcessor.class);
private static final String DOCKERFILE_JVM = "Dockerfile.jvm";
private static final String DOCKERFILE_NATIVE = "Dockerfile.native";
@Inject
BuildProducer<ArtifactResultBuildItem> artifact;
@BuildStep(onlyIf = DockerBuild.class, onlyIfNot = NativeBuild.class)
public ContainerImageResultBuildItem dockerBuildFromJar(DockerConfig dockerConfig, ApplicationInfoBuildItem app,
@BuildStep(onlyIf = { IsNormal.class, DockerBuild.class }, onlyIfNot = NativeBuild.class)
public void dockerBuildFromJar(DockerConfig dockerConfig,
ContainerImageConfig containerImageConfig, // TODO: use to check whether we need to also push to registry
OutputTargetBuildItem out,
ContainerImageBuildItem containerImage, JarBuildItem jar) {
ContainerImageBuildItem containerImage,
BuildProducer<ArtifactResultBuildItem> artifactResultProducer,
BuildProducer<ContainerImageResultBuildItem> containerImageResultProducer,
// used to ensure that the jar has been built
JarBuildItem jar) {
log.info("Building docker image for jar.");
String image = containerImage.getImage();
ImageIdReader reader = new ImageIdReader();
buildContainerImage(dockerConfig, containerImage, out, reader, false);
artifact.produce(new ArtifactResultBuildItem(null, "jar-container", Collections.emptyMap()));
return new ContainerImageResultBuildItem(reader.getImageId(), ImageUtil.getRepository(containerImage.getImage()),
ImageUtil.getTag(containerImage.getImage()));
createContainerImage(containerImageConfig, dockerConfig, image, out, reader, false);
artifactResultProducer.produce(new ArtifactResultBuildItem(null, "jar-container", Collections.emptyMap()));
containerImageResultProducer.produce(
new ContainerImageResultBuildItem(reader.getImageId(), ImageUtil.getRepository(image),
ImageUtil.getTag(image)));
}
@BuildStep(onlyIf = { DockerBuild.class, NativeBuild.class })
public ContainerImageResultBuildItem dockerBuildFromNativeImage(DockerConfig dockerConfig, ApplicationInfoBuildItem app,
@BuildStep(onlyIf = { IsNormal.class, DockerBuild.class, NativeBuild.class })
public void dockerBuildFromNativeImage(DockerConfig dockerConfig,
ContainerImageConfig containerImageConfig,
ContainerImageBuildItem containerImage,
OutputTargetBuildItem out,
Optional<ContainerImageBuildItem> dockerImage,
BuildProducer<ArtifactResultBuildItem> artifactResultProducer,
BuildProducer<ContainerImageResultBuildItem> containerImageResultProducer,
// used to ensure that the native binary has been built
NativeImageBuildItem nativeImage) {
if (!NativeBinaryUtil.nativeIsLinuxBinary(nativeImage)) {
throw new RuntimeException(
"The native binary produced by the build is not a Linux binary and therefore cannot be used in a Linux container image. Consider adding \"quarkus.native.container-build=true\" to your configuration");
}
log.info("Building docker image for native image.");
String image = containerImage.getImage();
ImageIdReader reader = new ImageIdReader();
buildContainerImage(dockerConfig, containerImage, out, reader, true);
artifact.produce(new ArtifactResultBuildItem(null, "native-container", Collections.emptyMap()));
return new ContainerImageResultBuildItem(reader.getImageId(), ImageUtil.getRepository(containerImage.getImage()),
ImageUtil.getTag(containerImage.getImage()));
createContainerImage(containerImageConfig, dockerConfig, image, out, reader, true);
artifactResultProducer.produce(new ArtifactResultBuildItem(null, "native-container", Collections.emptyMap()));
containerImageResultProducer
.produce(new ContainerImageResultBuildItem(reader.getImageId(), ImageUtil.getRepository(image),
ImageUtil.getTag(image)));
}
private void buildContainerImage(DockerConfig dockerConfig, ContainerImageBuildItem containerImage,
private void createContainerImage(ContainerImageConfig containerImageConfig, DockerConfig dockerConfig, String image,
OutputTargetBuildItem out, ImageIdReader reader, boolean forNative) {
DockerfilePaths dockerfilePaths = getDockerfilePaths(dockerConfig, forNative, out);
ExecUtil.exec(out.getOutputDirectory().toFile(),
reader,
"docker", "build",
"-f",
dockerfilePaths.getDockerfilePath().toAbsolutePath().toString(),
"-t", containerImage.getImage(),
dockerfilePaths.getDockerExecutionPath().toAbsolutePath().toString());
String[] buildArgs = { "build", "-f", dockerfilePaths.getDockerfilePath().toAbsolutePath().toString(), "-t", image,
dockerfilePaths.getDockerExecutionPath().toAbsolutePath().toString() };
boolean buildSuccessful = ExecUtil.exec(out.getOutputDirectory().toFile(), reader, "docker", buildArgs);
if (!buildSuccessful) {
throw dockerException(buildArgs);
}
if (containerImageConfig.execution == ContainerImageConfig.Execution.PUSH) {
String[] pushArgs = { "push", image };
boolean pushSuccessful = ExecUtil.exec("docker", pushArgs);
if (!pushSuccessful) {
throw dockerException(pushArgs);
}
}
}
private RuntimeException dockerException(String[] dockerArgs) {
return new RuntimeException(
"Execution of 'docker " + String.join(" ", dockerArgs) + "' failed. See docker output for more details");
}
private DockerfilePaths getDockerfilePaths(DockerConfig dockerConfig, boolean forNative,

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-container-image-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>quarkus-container-image-docker-parent</artifactId>
<name>Quarkus - Container - Image - Docker - Parent</name>
<packaging>pom</packaging>
<modules>
<module>deployment</module>
<module>runtime</module>
</modules>
</project>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-docker-parent</artifactId>
<version>999-SNAPSHOT</version>
</parent>
<artifactId>quarkus-container-image-docker</artifactId>
<name>Quarkus - Container - Image - Docker</name>
<description>Extension for building container images with Docker</description>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bootstrap-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,10 @@
---
name: "Container Image Docker"
metadata:
keywords:
- "docker"
- "container"
- "image"
categories:
- "cloud"
status: "preview"

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-jib-parent</artifactId>
<version>999-SNAPSHOT</version>
</parent>
<artifactId>quarkus-container-image-jib-deployment</artifactId>
<name>Quarkus - Container - Image - Jib - Deployment</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-jib</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-deployment</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>commons-logging-jboss-logging</artifactId>
</dependency>
<dependency>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,19 @@
package io.quarkus.container.image.jib.deployment;
import java.util.function.BooleanSupplier;
import io.quarkus.container.image.deployment.ContainerImageConfig;
public class JibBuild implements BooleanSupplier {
private final ContainerImageConfig containerImageConfig;
public JibBuild(ContainerImageConfig containerImageConfig) {
this.containerImageConfig = containerImageConfig;
}
@Override
public boolean getAsBoolean() {
return containerImageConfig.execution != ContainerImageConfig.Execution.NONE;
}
}

View File

@@ -0,0 +1,63 @@
package io.quarkus.container.image.jib.deployment;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;
@ConfigRoot(phase = ConfigPhase.BUILD_TIME)
public class JibConfig {
/**
* The base image to be used when a container image is being produced for the jar build
*/
@ConfigItem(defaultValue = "fabric8/java-alpine-openjdk8-jre")
public String baseJvmImage;
/**
* The base image to be used when a container image is being produced for the native binary build
*/
@ConfigItem(defaultValue = "registry.access.redhat.com/ubi8/ubi-minimal")
public String baseNativeImage;
/**
* Additional JVM arguments to pass to the JVM when starting the application
*/
@ConfigItem(defaultValue = "-Dquarkus.http.host=0.0.0.0,-Djava.util.logging.manager=org.jboss.logmanager.LogManager")
public List<String> jvmArguments;
/**
* Additional arguments to pass when starting the native application
*/
@ConfigItem(defaultValue = "-Dquarkus.http.host=0.0.0.0")
public List<String> nativeArguments;
/**
* Environment variables to add to the container image
*/
@ConfigItem
public Optional<Map<String, String>> environmentVariables;
//TODO: do the following config options belong in ContainerImageConfig ?
/**
* The username to use to authenticate with the registry
*/
@ConfigItem
public Optional<String> username;
/**
* The password to use to authenticate with the registry
*/
@ConfigItem
public Optional<String> password;
/**
* Whether or not insecure registries are allowed
*/
@ConfigItem(defaultValue = "false")
public boolean insecure;
}

View File

@@ -0,0 +1,220 @@
package io.quarkus.container.image.jib.deployment;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.jboss.logging.Logger;
import com.google.cloud.tools.jib.api.AbsoluteUnixPath;
import com.google.cloud.tools.jib.api.Containerizer;
import com.google.cloud.tools.jib.api.DockerDaemonImage;
import com.google.cloud.tools.jib.api.FilePermissions;
import com.google.cloud.tools.jib.api.ImageReference;
import com.google.cloud.tools.jib.api.InvalidImageReferenceException;
import com.google.cloud.tools.jib.api.JavaContainerBuilder;
import com.google.cloud.tools.jib.api.Jib;
import com.google.cloud.tools.jib.api.JibContainer;
import com.google.cloud.tools.jib.api.JibContainerBuilder;
import com.google.cloud.tools.jib.api.LayerConfiguration;
import com.google.cloud.tools.jib.api.LogEvent;
import com.google.cloud.tools.jib.api.RegistryImage;
import com.google.cloud.tools.jib.frontend.CredentialRetrieverFactory;
import io.quarkus.bootstrap.util.ZipUtils;
import io.quarkus.container.image.deployment.ContainerImageConfig;
import io.quarkus.container.image.deployment.util.NativeBinaryUtil;
import io.quarkus.container.spi.ContainerImageResultBuildItem;
import io.quarkus.deployment.IsNormal;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
import io.quarkus.deployment.builditem.MainClassBuildItem;
import io.quarkus.deployment.pkg.builditem.ArtifactResultBuildItem;
import io.quarkus.deployment.pkg.builditem.JarBuildItem;
import io.quarkus.deployment.pkg.builditem.NativeImageBuildItem;
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
import io.quarkus.deployment.pkg.steps.NativeBuild;
public class JibProcessor {
private static final Logger log = Logger.getLogger(JibProcessor.class);
private static final IsClassPredicate IS_CLASS_PREDICATE = new IsClassPredicate();
private static final String BINARY_NAME_IN_CONTAINER = "application";
@BuildStep(onlyIf = { IsNormal.class, JibBuild.class }, onlyIfNot = NativeBuild.class)
public void buildFromJar(ContainerImageConfig containerImageConfig, JibConfig jibConfig,
JarBuildItem sourceJarBuildItem,
MainClassBuildItem mainClassBuildItem,
OutputTargetBuildItem outputTargetBuildItem, ApplicationInfoBuildItem applicationInfo,
BuildProducer<ArtifactResultBuildItem> artifactResultProducer,
BuildProducer<ContainerImageResultBuildItem> containerImageResultProducer) {
JibContainerBuilder jibContainerBuilder = createContainerBuilderFromJar(jibConfig,
sourceJarBuildItem,
outputTargetBuildItem,
mainClassBuildItem);
JibContainer container = containerize(applicationInfo, containerImageConfig, jibConfig, jibContainerBuilder);
ImageReference targetImage = container.getTargetImage();
containerImageResultProducer.produce(new ContainerImageResultBuildItem(container.getImageId().getHash(),
targetImage.getRepository(), targetImage.getTag()));
artifactResultProducer.produce(new ArtifactResultBuildItem(null, "jar-container", Collections.emptyMap()));
}
@BuildStep(onlyIf = { IsNormal.class, JibBuild.class, NativeBuild.class })
public void buildFromNative(ContainerImageConfig containerImageConfig, JibConfig jibConfig,
NativeImageBuildItem nativeImageBuildItem,
ApplicationInfoBuildItem applicationInfo,
BuildProducer<ArtifactResultBuildItem> artifactResultProducer,
BuildProducer<ContainerImageResultBuildItem> containerImageResultProducer) {
if (!NativeBinaryUtil.nativeIsLinuxBinary(nativeImageBuildItem)) {
throw new RuntimeException(
"The native binary produced by the build is not a Linux binary and therefore cannot be used in a Linux container image. Consider adding \"quarkus.native.container-build=true\" to your configuration");
}
JibContainerBuilder jibContainerBuilder = createContainerBuilderFromNative(jibConfig, nativeImageBuildItem);
JibContainer container = containerize(applicationInfo, containerImageConfig, jibConfig, jibContainerBuilder);
ImageReference targetImage = container.getTargetImage();
containerImageResultProducer.produce(new ContainerImageResultBuildItem(container.getImageId().getHash(),
targetImage.getRepository(), targetImage.getTag()));
artifactResultProducer.produce(new ArtifactResultBuildItem(null, "native-container", Collections.emptyMap()));
}
private JibContainer containerize(ApplicationInfoBuildItem applicationInfo, ContainerImageConfig containerImageConfig,
JibConfig jibConfig,
JibContainerBuilder jibContainerBuilder) {
Containerizer containerizer = createContainerizer(containerImageConfig, jibConfig, applicationInfo);
try {
log.info("Starting container image build");
JibContainer container = jibContainerBuilder.containerize(containerizer);
log.infof("%s container image %s (%s)\n",
containerImageConfig.execution == ContainerImageConfig.Execution.PUSH ? "Pushed" : "Created",
container.getTargetImage(),
container.getDigest());
return container;
} catch (Exception e) {
throw new RuntimeException("Unable to create container image", e);
}
}
private Containerizer createContainerizer(ContainerImageConfig containerImageConfig, JibConfig jibConfig,
ApplicationInfoBuildItem applicationInfo) {
Containerizer containerizer;
ImageReference imageReference = getImageReference(containerImageConfig, applicationInfo);
if (containerImageConfig.execution == ContainerImageConfig.Execution.PUSH) {
CredentialRetrieverFactory credentialRetrieverFactory = CredentialRetrieverFactory.forImage(imageReference,
log::info);
RegistryImage registryImage = RegistryImage.named(imageReference);
registryImage.addCredentialRetriever(credentialRetrieverFactory.wellKnownCredentialHelpers());
registryImage.addCredentialRetriever(credentialRetrieverFactory.dockerConfig());
if (jibConfig.username.isPresent() && jibConfig.password.isPresent()) {
registryImage.addCredential(jibConfig.username.get(), jibConfig.password.get());
}
containerizer = Containerizer.to(registryImage);
} else {
containerizer = Containerizer.to(DockerDaemonImage.named(imageReference));
}
containerizer.setToolName("Quarkus");
containerizer.addEventHandler(LogEvent.class, (e) -> {
if (!e.getMessage().isEmpty()) {
log.log(toJBossLoggingLevel(e.getLevel()), e.getMessage());
}
});
containerizer.setAllowInsecureRegistries(jibConfig.insecure);
return containerizer;
}
private Logger.Level toJBossLoggingLevel(LogEvent.Level level) {
switch (level) {
case ERROR:
return Logger.Level.ERROR;
case WARN:
return Logger.Level.WARN;
case LIFECYCLE:
return Logger.Level.INFO;
default:
return Logger.Level.DEBUG;
}
}
private ImageReference getImageReference(ContainerImageConfig containerImageConfig,
ApplicationInfoBuildItem applicationInfo) {
return ImageReference.of(containerImageConfig.registry.orElse(null),
containerImageConfig.group + "/" + containerImageConfig.name.orElse(applicationInfo.getName()),
containerImageConfig.tag.orElse(applicationInfo.getVersion()));
}
private JibContainerBuilder createContainerBuilderFromJar(JibConfig jibConfig,
JarBuildItem sourceJarBuildItem,
OutputTargetBuildItem outputTargetBuildItem, MainClassBuildItem mainClassBuildItem) {
try {
// not ideal since this has been previously zipped - we would like to just reuse it
Path classesDir = outputTargetBuildItem.getOutputDirectory().resolve("jib");
ZipUtils.unzip(sourceJarBuildItem.getPath(), classesDir);
JavaContainerBuilder javaContainerBuilder = JavaContainerBuilder
.from(jibConfig.baseJvmImage)
.addResources(classesDir, IS_CLASS_PREDICATE.negate())
.addClasses(classesDir, IS_CLASS_PREDICATE)
.addJvmFlags(jibConfig.jvmArguments)
.setMainClass(mainClassBuildItem.getClassName());
if (sourceJarBuildItem.getLibraryDir() != null) {
javaContainerBuilder
.addDependencies(
Files.list(sourceJarBuildItem.getLibraryDir())
.filter(p -> Files.isRegularFile(p) && p.getFileName().toString().endsWith(".jar"))
.sorted(Comparator.comparing(Path::getFileName))
.collect(Collectors.toList()));
}
return javaContainerBuilder.toContainerBuilder()
.setEnvironment(jibConfig.environmentVariables.orElse(Collections.emptyMap()))
.setCreationTime(Instant.now());
} catch (IOException e) {
throw new UncheckedIOException(e);
} catch (InvalidImageReferenceException e) {
throw new RuntimeException(e);
}
}
private JibContainerBuilder createContainerBuilderFromNative(JibConfig jibConfig,
NativeImageBuildItem nativeImageBuildItem) {
List<String> entrypoint = new ArrayList<>(jibConfig.nativeArguments.size() + 1);
entrypoint.add("./" + BINARY_NAME_IN_CONTAINER);
entrypoint.addAll(jibConfig.nativeArguments);
try {
AbsoluteUnixPath workDirInContainer = AbsoluteUnixPath.get("/work");
return Jib.from(jibConfig.baseNativeImage)
.addLayer(LayerConfiguration.builder()
.addEntry(nativeImageBuildItem.getPath(), workDirInContainer.resolve(BINARY_NAME_IN_CONTAINER),
FilePermissions.fromOctalString("775"))
.build())
.setWorkingDirectory(workDirInContainer)
.setEntrypoint(entrypoint)
.setEnvironment(jibConfig.environmentVariables.orElse(Collections.emptyMap()))
.setCreationTime(Instant.now());
} catch (InvalidImageReferenceException e) {
throw new RuntimeException(e);
}
}
// TODO: this predicate is rather simplistic since it results in creating the directory structure in both the resources and classes so it should probably be improved to remove empty directories
private static class IsClassPredicate implements Predicate<Path> {
@Override
public boolean test(Path path) {
return path.getFileName().toString().endsWith(".class");
}
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-container-image-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>quarkus-container-image-jib-parent</artifactId>
<name>Quarkus - Container - Image - Jib - Parent</name>
<packaging>pom</packaging>
<modules>
<module>deployment</module>
<module>runtime</module>
</modules>
</project>

View File

@@ -6,13 +6,15 @@
<parent>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-parent</artifactId>
<artifactId>quarkus-container-image-jib-parent</artifactId>
<version>999-SNAPSHOT</version>
</parent>
<artifactId>quarkus-container</artifactId>
<name>Quarkus - Container - Runtime</name>
<description>Manage container builds</description>
<artifactId>quarkus-container-image-jib</artifactId>
<name>Quarkus - Container - Image - Jib</name>
<description>Extension for building container images with Jib</description>
<build>
<plugins>
<plugin>
@@ -33,6 +35,4 @@
</plugin>
</plugins>
</build>
</project>
</project>

View File

@@ -0,0 +1,10 @@
---
name: "Container Image Jib"
metadata:
keywords:
- "jib"
- "container"
- "image"
categories:
- "cloud"
status: "preview"

View File

@@ -3,13 +3,13 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-container-parent</artifactId>
<artifactId>quarkus-container-image-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>quarkus-container-deployment</artifactId>
<artifactId>quarkus-container-image-deployment</artifactId>
<name>Quarkus - Container - Deployment</name>
<dependencies>
@@ -19,7 +19,7 @@
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-spi</artifactId>
<artifactId>quarkus-container-image-spi</artifactId>
</dependency>
</dependencies>

View File

@@ -0,0 +1,54 @@
package io.quarkus.container.image.deployment;
import java.util.Optional;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigRoot;
@ConfigRoot
public class ContainerImageConfig {
/**
* The container registry to use
*/
@ConfigItem
public Optional<String> registry;
/**
* The group the container image will be part of
*/
@ConfigItem(defaultValue = "${user.name}")
public String group;
/**
* The name of the container image. If not set defaults to the application name
*/
@ConfigItem
public Optional<String> name;
/**
* The tag of the container image. If not set defaults to the application version
*/
@ConfigItem
public Optional<String> tag;
/**
* Controls what kind of execution is needed.
* <ul>
* <li>{@link io.quarkus.container.image.deployment.ContainerImageConfig.Execution#NONE} means that no container image will
* be created</li>
* <li>{@link io.quarkus.container.image.deployment.ContainerImageConfig.Execution#BUILD} will result in a container image
* being created locally</li>
* <li>{@link io.quarkus.container.image.deployment.ContainerImageConfig.Execution#PUSH} will result in a container image
* being pushed to the specified registry</li>
* </ul>
*/
@ConfigItem(defaultValue = "none")
public Execution execution;
public enum Execution {
NONE,
BUILD,
PUSH
}
}

View File

@@ -0,0 +1,18 @@
package io.quarkus.container.image.deployment;
import io.quarkus.container.image.deployment.util.ImageUtil;
import io.quarkus.container.spi.ContainerImageBuildItem;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
public class ContainerProcessor {
@BuildStep
public ContainerImageBuildItem publishNativeImageInfo(ApplicationInfoBuildItem app,
ContainerImageConfig containerImageConfig) {
String image = ImageUtil.getImage(containerImageConfig.registry, containerImageConfig.group,
containerImageConfig.name.orElse(app.getName()), containerImageConfig.tag.orElse(app.getVersion()));
return new ContainerImageBuildItem(image);
}
}

View File

@@ -1,13 +1,16 @@
package io.quarkus.container.deployment.util;
package io.quarkus.container.image.deployment.util;
import java.util.Optional;
public class ImageUtil {
public final class ImageUtil {
private static final String SLASH = "/";
private static final String COLN = ":";
private ImageUtil() {
}
/**
* Create an image from the individual parts.
*

View File

@@ -0,0 +1,31 @@
package io.quarkus.container.image.deployment.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import io.quarkus.deployment.pkg.builditem.NativeImageBuildItem;
public final class NativeBinaryUtil {
private NativeBinaryUtil() {
}
/**
* Checks if the file is a linux binary by checking the first bytes of the file against the ELF magic number
*/
public static boolean nativeIsLinuxBinary(NativeImageBuildItem nativeImageBuildItem) {
File file = nativeImageBuildItem.getPath().toFile();
try (FileInputStream fileInputStream = new FileInputStream(file)) {
byte[] firstBytes = new byte[4];
int readBytes = fileInputStream.read(firstBytes);
if (readBytes != 4) {
return false;
}
return (firstBytes[0] == 0x7f && firstBytes[1] == 0x45 && firstBytes[2] == 0x4c && firstBytes[3] == 0x46);
} catch (IOException e) {
throw new UncheckedIOException("Unable to determine type of native binary " + nativeImageBuildItem.getPath(), e);
}
}
}

View File

@@ -10,12 +10,13 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>quarkus-container-parent</artifactId>
<name>Quarkus - Container</name>
<artifactId>quarkus-container-image-parent</artifactId>
<name>Quarkus - Container Image</name>
<packaging>pom</packaging>
<modules>
<module>deployment</module>
<module>runtime</module>
<module>spi</module>
<module>container-image-docker</module>
<module>container-image-jib</module>
</modules>
</project>

View File

@@ -2,14 +2,14 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-container-parent</artifactId>
<artifactId>quarkus-container-image-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>quarkus-container-spi</artifactId>
<name>Quarkus - Container - SPI</name>
<artifactId>quarkus-container-image-spi</artifactId>
<name>Quarkus - Container - Image - SPI</name>
<description>Extensions that provide Container features should include this module and the corresponding BuildItems</description>
<dependencies>

View File

@@ -1,45 +0,0 @@
package io.quarkus.container.deployment;
import java.util.Optional;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigRoot;
@ConfigRoot
public class ContainerConfig {
/**
* The container registry to use
*/
@ConfigItem
public Optional<String> registry;
/**
* The group the container image will be part of
*/
@ConfigItem(defaultValue = "${user.name}")
public String group;
/**
* The name of the container image. If not set defaults to the application name
*/
@ConfigItem
public Optional<String> name;
/**
* The tag of the container image. If not set defaults to the application version
*/
@ConfigItem
public Optional<String> tag;
/**
* Flag that specifies if container build is enabled
*/
@ConfigItem
public boolean build;
/**
* Flag that specifies if container deploy is enabled
*/
@ConfigItem
public boolean deploy;
}

View File

@@ -1,35 +0,0 @@
package io.quarkus.container.deployment;
import io.quarkus.container.deployment.util.ImageUtil;
import io.quarkus.container.spi.ContainerImageBuildItem;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
import io.quarkus.deployment.pkg.steps.NativeBuild;
public class ContainerProcessor {
private ContainerConfig containerConfig;
@BuildStep(onlyIfNot = NativeBuild.class)
public ContainerImageBuildItem publishImageInfo(ApplicationInfoBuildItem app) {
String image = ImageUtil.getImage(containerConfig.registry, containerConfig.group,
containerConfig.name.orElse(app.getName()), containerConfig.tag.orElse(app.getVersion()));
return new ContainerImageBuildItem(image);
}
@BuildStep(onlyIf = NativeBuild.class)
public ContainerImageBuildItem publishNativeImageInfo(ApplicationInfoBuildItem app) {
String image = ImageUtil.getImage(containerConfig.registry, containerConfig.group,
containerConfig.name.orElse(app.getName()), containerConfig.tag.orElse(app.getVersion() + "-native"));
return new ContainerImageBuildItem(image);
}
public ContainerConfig getContainerConfig() {
return this.containerConfig;
}
public void setContainerConfig(ContainerConfig containerConfig) {
this.containerConfig = containerConfig;
}
}

View File

@@ -1,9 +0,0 @@
---
name: "Docker"
metadata:
keywords:
- "docker"
guide: "https://quarkus.io/guides/docker"
categories:
- "cloud"
status: "stable"

View File

@@ -2,7 +2,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-kubernetes-parent</artifactId>
<artifactId>quarkus-kubernetes-client-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
</parent>

View File

@@ -15,11 +15,11 @@
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-deployment</artifactId>
<artifactId>quarkus-container-image-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-spi</artifactId>
<artifactId>quarkus-container-image-spi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>

View File

@@ -14,8 +14,7 @@ import java.util.function.Function;
import org.jboss.logging.Logger;
import io.quarkus.container.deployment.ContainerConfig;
import io.quarkus.container.deployment.DockerBuild.OutputFilter;
import io.quarkus.container.image.deployment.ContainerImageConfig;
import io.quarkus.deployment.util.ExecUtil;
public class KubernetesDeploy implements BooleanSupplier {
@@ -23,16 +22,17 @@ public class KubernetesDeploy implements BooleanSupplier {
private final Logger LOGGER = Logger.getLogger(KubernetesDeploy.class);
private KubernetesConfig kubernetesConfig;
private ContainerConfig containerConfig;
private ContainerImageConfig containerImageConfig;
KubernetesDeploy(ContainerConfig containerConfig, KubernetesConfig kubernetesConfig) {
this.containerConfig = containerConfig;
KubernetesDeploy(ContainerImageConfig containerImageConfig, KubernetesConfig kubernetesConfig) {
this.containerImageConfig = containerImageConfig;
this.kubernetesConfig = kubernetesConfig;
}
@Override
public boolean getAsBoolean() {
if (containerConfig.deploy) {
// TODO: I think this is wrong for s2i
if (containerImageConfig.execution == ContainerImageConfig.Execution.PUSH) {
OutputFilter filter = new OutputFilter();
try {
if (kubernetesConfig.getDeploymentTarget().contains(DeploymentTarget.OPENSHIFT)) {

View File

@@ -130,7 +130,7 @@
<module>scala</module>
<!-- Kubernetes -->
<module>container</module>
<module>container-image</module>
<module>kubernetes</module>
<module>kubernetes-client</module>

View File

@@ -7,29 +7,28 @@
<artifactId>quarkus-integration-tests-parent</artifactId>
<version>999-SNAPSHOT</version>
</parent>
<artifactId>quarkus-integration-test-container</artifactId>
<name>Quarkus - Integration Tests - Container extension</name>
<artifactId>quarkus-integration-test-container-image</artifactId>
<name>Quarkus - Integration Tests - Jib extension</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.j2objc</groupId>
<artifactId>j2objc-annotations</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core-deployment</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-deployment</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-maven</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<testResources>

View File

@@ -0,0 +1 @@
invoker.goals=clean package -Dquarkus.container-image.execution=build

View File

@@ -0,0 +1,117 @@
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.acme</groupId>
<artifactId>container-build-docker</artifactId>
<version>0.1-SNAPSHOT</version>
<properties>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<surefire-plugin.version>2.22.0</surefire-plugin.version>
<maven.compiler.source>1.8</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bom</artifactId>
<version>@project.version@</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-docker</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>@project.version@</version>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemProperties>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>@project.version@</version>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
<configuration>
<enableHttpUrlHandler>true</enableHttpUrlHandler>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemProperties>
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@@ -0,0 +1,22 @@
####
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
#
# Before building the docker image run:
#
# mvn package
#
# Then, build the image with:
#
# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/getting-started-jvm .
#
# Then run the container using:
#
# docker run -i --rm -p 8080:8080 quarkus/getting-started-jvm
#
###
FROM fabric8/java-alpine-openjdk8-jre
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
ENV AB_ENABLED=jmx_exporter
COPY target/lib/* /deployments/lib/
COPY target/*-runner.jar /deployments/app.jar
ENTRYPOINT [ "/deployments/run-java.sh" ]

View File

@@ -0,0 +1,12 @@
import io.quarkus.deployment.util.ExecUtil
try {
ExecUtil.exec("docker", "version", "--format", "'{{.Server.Version}}'")
} catch (Exception ignored) {
println "Docker not found"
return
}
String group = System.getProperty("user.name")
assert ExecUtil.exec("docker", "images", group + "/container-build-docker")
assert ExecUtil.exec("docker", "rmi", group + "/container-build-docker:0.1-SNAPSHOT")

View File

@@ -0,0 +1 @@
invoker.goals=clean package -Dquarkus.container-image.execution=build

View File

@@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.acme</groupId>
<artifactId>container-build</artifactId>
<artifactId>container-build-jib</artifactId>
<version>0.1-SNAPSHOT</version>
<properties>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
@@ -30,7 +30,7 @@
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container</artifactId>
<artifactId>quarkus-container-image-jib</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>

View File

@@ -0,0 +1,16 @@
package org.acme;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/hello")
public class Hello {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "hello";
}
}

View File

@@ -0,0 +1,2 @@
# Configuration file
# key = value

View File

@@ -0,0 +1,12 @@
import io.quarkus.deployment.util.ExecUtil
try {
ExecUtil.exec("docker", "version", "--format", "'{{.Server.Version}}'")
} catch (Exception ignored) {
println "Docker not found"
return
}
String group = System.getProperty("user.name")
assert ExecUtil.exec("docker", "images", group + "/container-build-jib")
assert ExecUtil.exec("docker", "rmi", group + "/container-build-jib:0.1-SNAPSHOT")

View File

@@ -1,2 +0,0 @@
# invoker.goals=clean package -Dquarkus.container.build=true -Dquarkus.package.type=native
invoker.goals=clean package -Dquarkus.container.build=true

View File

@@ -1,5 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -69,7 +67,8 @@
<module>amazon-lambda-http</module>
<module>amazon-lambda-http-resteasy</module>
<module>kogito</module>
<module>container</module>
<module>kogito-maven</module>
<module>container-image</module>
<module>optaplanner-jackson</module>
<module>kubernetes</module>
<module>kubernetes-client</module>