mirror of
https://github.com/jlengrand/quarkus.git
synced 2026-03-10 08:41:22 +00:00
Introduce jib extension as an alternative for building container images and harmonize code between it and the docker extension
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
@@ -1,4 +1,4 @@
|
||||
package io.quarkus.container.deployment;
|
||||
package io.quarkus.container.image.docker.deployment;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -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,
|
||||
20
extensions/container-image/container-image-docker/pom.xml
Normal file
20
extensions/container-image/container-image-docker/pom.xml
Normal 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>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: "Container Image Docker"
|
||||
metadata:
|
||||
keywords:
|
||||
- "docker"
|
||||
- "container"
|
||||
- "image"
|
||||
categories:
|
||||
- "cloud"
|
||||
status: "preview"
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
20
extensions/container-image/container-image-jib/pom.xml
Normal file
20
extensions/container-image/container-image-jib/pom.xml
Normal 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>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: "Container Image Jib"
|
||||
metadata:
|
||||
keywords:
|
||||
- "jib"
|
||||
- "container"
|
||||
- "image"
|
||||
categories:
|
||||
- "cloud"
|
||||
status: "preview"
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.
|
||||
*
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
name: "Docker"
|
||||
metadata:
|
||||
keywords:
|
||||
- "docker"
|
||||
guide: "https://quarkus.io/guides/docker"
|
||||
categories:
|
||||
- "cloud"
|
||||
status: "stable"
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
<module>scala</module>
|
||||
|
||||
<!-- Kubernetes -->
|
||||
<module>container</module>
|
||||
<module>container-image</module>
|
||||
<module>kubernetes</module>
|
||||
<module>kubernetes-client</module>
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -0,0 +1 @@
|
||||
invoker.goals=clean package -Dquarkus.container-image.execution=build
|
||||
@@ -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>
|
||||
@@ -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" ]
|
||||
@@ -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")
|
||||
@@ -0,0 +1 @@
|
||||
invoker.goals=clean package -Dquarkus.container-image.execution=build
|
||||
@@ -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>
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
# Configuration file
|
||||
# key = value
|
||||
@@ -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")
|
||||
@@ -1,2 +0,0 @@
|
||||
# invoker.goals=clean package -Dquarkus.container.build=true -Dquarkus.package.type=native
|
||||
invoker.goals=clean package -Dquarkus.container.build=true
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user