diff --git a/bom/deployment/pom.xml b/bom/deployment/pom.xml
index 7d81fe6ee..0c4ccca63 100644
--- a/bom/deployment/pom.xml
+++ b/bom/deployment/pom.xml
@@ -473,12 +473,22 @@
io.quarkus
- quarkus-container-deployment
+ quarkus-container-image-deployment
${project.version}
io.quarkus
- quarkus-container-spi
+ quarkus-container-image-spi
+ ${project.version}
+
+
+ io.quarkus
+ quarkus-container-image-docker-deployment
+ ${project.version}
+
+
+ io.quarkus
+ quarkus-container-image-jib-deployment
${project.version}
diff --git a/bom/runtime/pom.xml b/bom/runtime/pom.xml
index 0bc3c902a..15de4cc01 100644
--- a/bom/runtime/pom.xml
+++ b/bom/runtime/pom.xml
@@ -185,6 +185,8 @@
1.1.1
2.5.2
2.2.0
+ 0.13.0
+ 1.34.0
@@ -713,7 +715,12 @@
io.quarkus
- quarkus-container
+ quarkus-container-image-docker
+ ${project.version}
+
+
+ io.quarkus
+ quarkus-container-image-jib
${project.version}
@@ -2857,6 +2864,24 @@
quarkus-banner
${project.version}
+
+
+
+ com.google.cloud.tools
+ jib-core
+ ${jib-core.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ com.google.http-client
+ google-http-client
+ ${google-http-client.version}
+
diff --git a/extensions/container-image/container-image-docker/deployment/pom.xml b/extensions/container-image/container-image-docker/deployment/pom.xml
new file mode 100644
index 000000000..a19f8d401
--- /dev/null
+++ b/extensions/container-image/container-image-docker/deployment/pom.xml
@@ -0,0 +1,44 @@
+
+
+ 4.0.0
+
+
+ io.quarkus
+ quarkus-container-image-docker-parent
+ 999-SNAPSHOT
+
+
+ quarkus-container-image-docker-deployment
+ Quarkus - Container - Image - Docker - Deployment
+
+
+
+ io.quarkus
+ quarkus-container-image-docker
+
+
+ io.quarkus
+ quarkus-container-image-deployment
+
+
+
+
+
+
+ maven-compiler-plugin
+
+
+
+ io.quarkus
+ quarkus-extension-processor
+ ${project.version}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/extensions/container/deployment/src/main/java/io/quarkus/container/deployment/DockerBuild.java b/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerBuild.java
similarity index 84%
rename from extensions/container/deployment/src/main/java/io/quarkus/container/deployment/DockerBuild.java
rename to extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerBuild.java
index a33ad865d..72eaa49ec 100644
--- a/extensions/container/deployment/src/main/java/io/quarkus/container/deployment/DockerBuild.java
+++ b/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerBuild.java
@@ -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;
diff --git a/extensions/container/deployment/src/main/java/io/quarkus/container/deployment/DockerConfig.java b/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerConfig.java
similarity index 94%
rename from extensions/container/deployment/src/main/java/io/quarkus/container/deployment/DockerConfig.java
rename to extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerConfig.java
index b3ae56e0d..d4f177993 100644
--- a/extensions/container/deployment/src/main/java/io/quarkus/container/deployment/DockerConfig.java
+++ b/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerConfig.java
@@ -1,4 +1,4 @@
-package io.quarkus.container.deployment;
+package io.quarkus.container.image.docker.deployment;
import java.util.Optional;
diff --git a/extensions/container/deployment/src/main/java/io/quarkus/container/deployment/DockerBuildStep.java b/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerProcessor.java
similarity index 69%
rename from extensions/container/deployment/src/main/java/io/quarkus/container/deployment/DockerBuildStep.java
rename to extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerProcessor.java
index 6c02bf178..91470e818 100644
--- a/extensions/container/deployment/src/main/java/io/quarkus/container/deployment/DockerBuildStep.java
+++ b/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerProcessor.java
@@ -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 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 artifactResultProducer,
+ BuildProducer 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 dockerImage,
+ BuildProducer artifactResultProducer,
+ BuildProducer 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,
diff --git a/extensions/container-image/container-image-docker/pom.xml b/extensions/container-image/container-image-docker/pom.xml
new file mode 100644
index 000000000..8c6c6a2ec
--- /dev/null
+++ b/extensions/container-image/container-image-docker/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ quarkus-container-image-parent
+ io.quarkus
+ 999-SNAPSHOT
+
+ 4.0.0
+
+ quarkus-container-image-docker-parent
+ Quarkus - Container - Image - Docker - Parent
+ pom
+
+ deployment
+ runtime
+
+
+
\ No newline at end of file
diff --git a/extensions/container-image/container-image-docker/runtime/pom.xml b/extensions/container-image/container-image-docker/runtime/pom.xml
new file mode 100644
index 000000000..a33c635ac
--- /dev/null
+++ b/extensions/container-image/container-image-docker/runtime/pom.xml
@@ -0,0 +1,38 @@
+
+
+ 4.0.0
+
+
+ io.quarkus
+ quarkus-container-image-docker-parent
+ 999-SNAPSHOT
+
+
+ quarkus-container-image-docker
+ Quarkus - Container - Image - Docker
+ Extension for building container images with Docker
+
+
+
+
+
+ io.quarkus
+ quarkus-bootstrap-maven-plugin
+
+
+ maven-compiler-plugin
+
+
+
+ io.quarkus
+ quarkus-extension-processor
+ ${project.version}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/extensions/container-image/container-image-docker/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/container-image/container-image-docker/runtime/src/main/resources/META-INF/quarkus-extension.yaml
new file mode 100644
index 000000000..df9380b2a
--- /dev/null
+++ b/extensions/container-image/container-image-docker/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -0,0 +1,10 @@
+---
+name: "Container Image Docker"
+metadata:
+ keywords:
+ - "docker"
+ - "container"
+ - "image"
+ categories:
+ - "cloud"
+ status: "preview"
diff --git a/extensions/container-image/container-image-jib/deployment/pom.xml b/extensions/container-image/container-image-jib/deployment/pom.xml
new file mode 100644
index 000000000..7a54d45c9
--- /dev/null
+++ b/extensions/container-image/container-image-jib/deployment/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+
+
+ io.quarkus
+ quarkus-container-image-jib-parent
+ 999-SNAPSHOT
+
+
+ quarkus-container-image-jib-deployment
+ Quarkus - Container - Image - Jib - Deployment
+
+
+
+ io.quarkus
+ quarkus-container-image-jib
+
+
+ io.quarkus
+ quarkus-container-image-deployment
+
+
+ org.jboss.logging
+ commons-logging-jboss-logging
+
+
+ com.google.cloud.tools
+ jib-core
+
+
+
+
+
+
+ maven-compiler-plugin
+
+
+
+ io.quarkus
+ quarkus-extension-processor
+ ${project.version}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibBuild.java b/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibBuild.java
new file mode 100644
index 000000000..e0bb6128d
--- /dev/null
+++ b/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibBuild.java
@@ -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;
+ }
+}
diff --git a/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibConfig.java b/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibConfig.java
new file mode 100644
index 000000000..36b08e969
--- /dev/null
+++ b/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibConfig.java
@@ -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 jvmArguments;
+
+ /**
+ * Additional arguments to pass when starting the native application
+ */
+ @ConfigItem(defaultValue = "-Dquarkus.http.host=0.0.0.0")
+ public List nativeArguments;
+
+ /**
+ * Environment variables to add to the container image
+ */
+ @ConfigItem
+ public Optional