This is an automated email from the ASF dual-hosted git repository.

jbonofre pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/karaf.git


The following commit(s) were added to refs/heads/main by this push:
     new e637cf5232 Allow configuring base docker image in DockerfileMojo 
(#2785) (#2839)
e637cf5232 is described below

commit e637cf523263542619a84ac56f0d4a505226e6cb
Author: gaurav kumar pandey <[email protected]>
AuthorDate: Sat Sep 12 23:01:54 2026 +0530

    Allow configuring base docker image in DockerfileMojo (#2785) (#2839)
    
    * Allow configuring base docker image in DockerfileMojo (#2785)
    
    - Add configurable 'image' parameter to DockerfileMojo defaulting to 
eclipse-temurin:11-jre
    - Validate 'image' and 'command' parameters, falling back to defaults on 
blank values and rejecting newlines
    - Add DockerfileMojoTest covering default, custom, blank fallback, and 
validation scenarios
    - Strengthen test-dockerfile IT verification
    - Update developer documentation with image and command parameters and fix 
XML typo
    
    * Address review feedback: bind command property and update docker example
---
 examples/karaf-docker-example/README.md            |   4 +-
 .../karaf-docker-example-dynamic-dist/pom.xml      |   1 +
 .../karaf-docker-example-static-dist/pom.xml       |   3 +
 .../developer-guide/karaf-maven-plugin.adoc        |  10 +-
 .../src/it/test-dockerfile/verify.bsh              |   8 +-
 .../org/apache/karaf/tooling/DockerfileMojo.java   |  23 ++-
 .../apache/karaf/tooling/DockerfileMojoTest.java   | 175 +++++++++++++++++++++
 7 files changed, 217 insertions(+), 7 deletions(-)

diff --git a/examples/karaf-docker-example/README.md 
b/examples/karaf-docker-example/README.md
index a57b3169e1..322e665423 100644
--- a/examples/karaf-docker-example/README.md
+++ b/examples/karaf-docker-example/README.md
@@ -123,7 +123,7 @@ You can build the docker image using the generated 
`Dockerfile`:
 $ cd karaf-docker-example-static-dist/target
 $ docker build -t mykaraf .
 Sending build context to Docker daemon  78.08MB
-Step 1/7 : FROM openjdk:8-jre
+Step 1/7 : FROM eclipse-temurin:17-jre
  ---> d60154a7d9b2
 Step 2/7 : ENV KARAF_INSTALL_PATH /opt
  ---> Using cache
@@ -259,7 +259,7 @@ You can build the docker image using the generated 
`Dockerfile`:
 $ cd karaf-docker-example-dynamic-dist/target
 $ docker build -t mykaraf .
 Sending build context to Docker daemon  102.5MB
-Step 1/7 : FROM openjdk:8-jre
+Step 1/7 : FROM eclipse-temurin:17-jre
  ---> 19c48cc84cc6
 Step 2/7 : ENV KARAF_INSTALL_PATH /opt
  ---> Running in 8a9a42db2395
diff --git 
a/examples/karaf-docker-example/karaf-docker-example-dynamic-dist/pom.xml 
b/examples/karaf-docker-example/karaf-docker-example-dynamic-dist/pom.xml
index 0d444b96cf..737f04e70c 100644
--- a/examples/karaf-docker-example/karaf-docker-example-dynamic-dist/pom.xml
+++ b/examples/karaf-docker-example/karaf-docker-example-dynamic-dist/pom.xml
@@ -101,6 +101,7 @@
                             <goal>dockerfile</goal>
                         </goals>
                         <configuration>
+                            <image>eclipse-temurin:17-jre</image>
                             <command>["karaf"]</command>
                         </configuration>
                     </execution>
diff --git 
a/examples/karaf-docker-example/karaf-docker-example-static-dist/pom.xml 
b/examples/karaf-docker-example/karaf-docker-example-static-dist/pom.xml
index 6113f13009..962cb65914 100644
--- a/examples/karaf-docker-example/karaf-docker-example-static-dist/pom.xml
+++ b/examples/karaf-docker-example/karaf-docker-example-static-dist/pom.xml
@@ -96,6 +96,9 @@
                         <goals>
                             <goal>dockerfile</goal>
                         </goals>
+                        <configuration>
+                            <image>eclipse-temurin:17-jre</image>
+                        </configuration>
                     </execution>
                 </executions>
                 <configuration>
diff --git a/manual/src/main/asciidoc/developer-guide/karaf-maven-plugin.adoc 
b/manual/src/main/asciidoc/developer-guide/karaf-maven-plugin.adoc
index 47090ee60a..5b62598185 100644
--- a/manual/src/main/asciidoc/developer-guide/karaf-maven-plugin.adoc
+++ b/manual/src/main/asciidoc/developer-guide/karaf-maven-plugin.adoc
@@ -991,6 +991,14 @@ The `karaf:dockerfile` goal creates a ready to use 
Dockerfile for a given Karaf
 |`assembly`
 |`File`
 |The directory containing the Karaf assembly (as generated by 
`karaf:assembly`). Default value: ${project.build.directory}/assembly
+
+|`command`
+|`String`
+|The CMD command instruction to include in the generated Dockerfile. Default 
value: `["karaf", "run"]`
+
+|`image`
+|`String`
+|The base Docker image (FROM instruction) to use. Default value: 
`eclipse-temurin:11-jre`
 |===
 
 ===== Docker
@@ -1008,7 +1016,7 @@ This goal requires a local Docker daemon and runs only on 
Unix. The `docker` com
 <execution>
     <id>docker</id>
     <goals>
-        <goal>docker</docker>
+        <goal>docker</goal>
     </goals>
 </execution>
 ----
diff --git a/tooling/karaf-maven-plugin/src/it/test-dockerfile/verify.bsh 
b/tooling/karaf-maven-plugin/src/it/test-dockerfile/verify.bsh
index f42d4205c9..e96f658702 100644
--- a/tooling/karaf-maven-plugin/src/it/test-dockerfile/verify.bsh
+++ b/tooling/karaf-maven-plugin/src/it/test-dockerfile/verify.bsh
@@ -22,4 +22,10 @@ import java.lang.*;
 import java.util.*;
 
 File generated = new File(basedir, "target/Dockerfile");
-return generated.exists();
\ No newline at end of file
+if (!generated.exists()) {
+    return false;
+}
+BufferedReader reader = new BufferedReader(new FileReader(generated));
+String line = reader.readLine();
+reader.close();
+return line != null && line.startsWith("FROM eclipse-temurin:11-jre");
\ No newline at end of file
diff --git 
a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/DockerfileMojo.java
 
b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/DockerfileMojo.java
index 83fa290cb7..b8d809e97f 100644
--- 
a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/DockerfileMojo.java
+++ 
b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/DockerfileMojo.java
@@ -31,29 +31,46 @@ import java.io.FileWriter;
 @Mojo(name = "dockerfile", defaultPhase = LifecyclePhase.PACKAGE)
 public class DockerfileMojo extends MojoSupport {
 
+    private static final String DEFAULT_IMAGE = "eclipse-temurin:11-jre";
+    private static final String DEFAULT_COMMAND = "[\"karaf\", \"run\"]";
+
     @Parameter(defaultValue = "${project.build.directory}")
     private File destDir;
 
     @Parameter(defaultValue = "${project.build.directory}/assembly")
     private File assembly;
 
-    @Parameter(defaultValue = "[\"karaf\", \"run\"]")
+    @Parameter(defaultValue = DEFAULT_COMMAND, property = "command")
     private String command;
 
+    @Parameter(defaultValue = DEFAULT_IMAGE, property = "image")
+    private String image;
+
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
         getLog().info("Creating Dockerfile");
+
+        String baseImage = (image == null || image.trim().isEmpty()) ? 
DEFAULT_IMAGE : image.trim();
+        String cmd = (command == null || command.trim().isEmpty()) ? 
DEFAULT_COMMAND : command.trim();
+
+        if (baseImage.contains("\n") || baseImage.contains("\r")) {
+            throw new MojoExecutionException("Invalid image: base image cannot 
contain newline characters");
+        }
+        if (cmd.contains("\n") || cmd.contains("\r")) {
+            throw new MojoExecutionException("Invalid command: command cannot 
contain newline characters");
+        }
+
         File dockerFile = new File(destDir, "Dockerfile");
         try {
             StringBuilder buffer = new StringBuilder();
-            buffer.append("FROM eclipse-temurin:11-jre").append("\n");
+            buffer.append("FROM ").append(baseImage).append("\n");
             buffer.append("ENV KARAF_INSTALL_PATH /opt").append("\n");
             buffer.append("ENV KARAF_HOME 
$KARAF_INSTALL_PATH/apache-karaf").append("\n");
             buffer.append("ENV KARAF_EXEC exec").append("\n");
             buffer.append("ENV PATH $PATH:$KARAF_HOME/bin").append("\n");
             buffer.append("COPY ").append(assembly.getName()).append(" 
$KARAF_HOME").append("\n");
             buffer.append("EXPOSE 8101 1099 44444 8181").append("\n");
-            buffer.append("CMD ").append(command).append("\n");
+            buffer.append("CMD ").append(cmd).append("\n");
             try (FileWriter writer = new FileWriter(dockerFile)) {
                 writer.write(buffer.toString());
             }
diff --git 
a/tooling/karaf-maven-plugin/src/test/java/org/apache/karaf/tooling/DockerfileMojoTest.java
 
b/tooling/karaf-maven-plugin/src/test/java/org/apache/karaf/tooling/DockerfileMojoTest.java
new file mode 100644
index 0000000000..15e52b7c1e
--- /dev/null
+++ 
b/tooling/karaf-maven-plugin/src/test/java/org/apache/karaf/tooling/DockerfileMojoTest.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.tooling;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.nio.file.Files;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class DockerfileMojoTest {
+
+    @Rule
+    public final TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+    @Test
+    public void testDefaultDockerfileGeneration() throws Exception {
+        DockerfileMojo mojo = new DockerfileMojo();
+        File destDir = temporaryFolder.newFolder("target");
+        File assembly = new File(destDir, "assembly");
+
+        setPrivateField(mojo, "destDir", destDir);
+        setPrivateField(mojo, "assembly", assembly);
+        setPrivateField(mojo, "command", "[\"karaf\", \"run\"]");
+        setPrivateField(mojo, "image", "eclipse-temurin:11-jre");
+
+        mojo.execute();
+
+        File dockerfile = new File(destDir, "Dockerfile");
+        assertTrue("Dockerfile should be created", dockerfile.exists());
+
+        List<String> lines = Files.readAllLines(dockerfile.toPath());
+        assertEquals("FROM eclipse-temurin:11-jre", lines.get(0));
+        assertEquals("ENV KARAF_INSTALL_PATH /opt", lines.get(1));
+        assertEquals("ENV KARAF_HOME $KARAF_INSTALL_PATH/apache-karaf", 
lines.get(2));
+        assertEquals("ENV KARAF_EXEC exec", lines.get(3));
+        assertEquals("ENV PATH $PATH:$KARAF_HOME/bin", lines.get(4));
+        assertEquals("COPY assembly $KARAF_HOME", lines.get(5));
+        assertEquals("EXPOSE 8101 1099 44444 8181", lines.get(6));
+        assertEquals("CMD [\"karaf\", \"run\"]", lines.get(7));
+    }
+
+    @Test
+    public void testCustomImageAndCommand() throws Exception {
+        DockerfileMojo mojo = new DockerfileMojo();
+        File destDir = temporaryFolder.newFolder("target-custom");
+        File assembly = new File(destDir, "custom-dist");
+
+        setPrivateField(mojo, "destDir", destDir);
+        setPrivateField(mojo, "assembly", assembly);
+        setPrivateField(mojo, "command", "[\"karaf\", \"server\"]");
+        setPrivateField(mojo, "image", "eclipse-temurin:17-jre");
+
+        mojo.execute();
+
+        File dockerfile = new File(destDir, "Dockerfile");
+        assertTrue("Dockerfile should be created", dockerfile.exists());
+
+        List<String> lines = Files.readAllLines(dockerfile.toPath());
+        assertEquals("FROM eclipse-temurin:17-jre", lines.get(0));
+        assertEquals("COPY custom-dist $KARAF_HOME", lines.get(5));
+        assertEquals("CMD [\"karaf\", \"server\"]", lines.get(7));
+    }
+
+    @Test
+    public void testBlankOrNullImageFallsBackToDefault() throws Exception {
+        String[] blankImages = new String[]{null, "", "   "};
+        for (int i = 0; i < blankImages.length; i++) {
+            DockerfileMojo mojo = new DockerfileMojo();
+            File destDir = temporaryFolder.newFolder("target-blank-image-" + 
i);
+            File assembly = new File(destDir, "assembly");
+
+            setPrivateField(mojo, "destDir", destDir);
+            setPrivateField(mojo, "assembly", assembly);
+            setPrivateField(mojo, "command", "[\"karaf\", \"run\"]");
+            setPrivateField(mojo, "image", blankImages[i]);
+
+            mojo.execute();
+
+            File dockerfile = new File(destDir, "Dockerfile");
+            assertTrue("Dockerfile should be created", dockerfile.exists());
+
+            List<String> lines = Files.readAllLines(dockerfile.toPath());
+            assertEquals("FROM eclipse-temurin:11-jre", lines.get(0));
+        }
+    }
+
+    @Test
+    public void testBlankOrNullCommandFallsBackToDefault() throws Exception {
+        String[] blankCommands = new String[]{null, "", "   "};
+        for (int i = 0; i < blankCommands.length; i++) {
+            DockerfileMojo mojo = new DockerfileMojo();
+            File destDir = temporaryFolder.newFolder("target-blank-cmd-" + i);
+            File assembly = new File(destDir, "assembly");
+
+            setPrivateField(mojo, "destDir", destDir);
+            setPrivateField(mojo, "assembly", assembly);
+            setPrivateField(mojo, "command", blankCommands[i]);
+            setPrivateField(mojo, "image", "eclipse-temurin:11-jre");
+
+            mojo.execute();
+
+            File dockerfile = new File(destDir, "Dockerfile");
+            assertTrue("Dockerfile should be created", dockerfile.exists());
+
+            List<String> lines = Files.readAllLines(dockerfile.toPath());
+            assertEquals("CMD [\"karaf\", \"run\"]", lines.get(7));
+        }
+    }
+
+    @Test(expected = MojoExecutionException.class)
+    public void testImageWithNewlineThrowsException() throws Exception {
+        DockerfileMojo mojo = new DockerfileMojo();
+        File destDir = temporaryFolder.newFolder("target-nl-image");
+        File assembly = new File(destDir, "assembly");
+
+        setPrivateField(mojo, "destDir", destDir);
+        setPrivateField(mojo, "assembly", assembly);
+        setPrivateField(mojo, "command", "[\"karaf\", \"run\"]");
+        setPrivateField(mojo, "image", "eclipse-temurin:11-jre\nRUN rm -rf /");
+
+        mojo.execute();
+    }
+
+    @Test(expected = MojoExecutionException.class)
+    public void testCommandWithNewlineThrowsException() throws Exception {
+        DockerfileMojo mojo = new DockerfileMojo();
+        File destDir = temporaryFolder.newFolder("target-nl-cmd");
+        File assembly = new File(destDir, "assembly");
+
+        setPrivateField(mojo, "destDir", destDir);
+        setPrivateField(mojo, "assembly", assembly);
+        setPrivateField(mojo, "command", "[\"karaf\", \"run\"]\nRUN rm -rf /");
+        setPrivateField(mojo, "image", "eclipse-temurin:11-jre");
+
+        mojo.execute();
+    }
+
+    private void setPrivateField(Object obj, String fieldName, Object value) 
throws Exception {
+        Class<?> aClass = obj.getClass();
+        while (aClass != null) {
+            try {
+                Field field = aClass.getDeclaredField(fieldName);
+                field.setAccessible(true);
+                field.set(obj, value);
+                return;
+            } catch (final NoSuchFieldException nsfe) {
+                aClass = aClass.getSuperclass();
+            }
+        }
+        fail("cant set " + fieldName);
+    }
+}

Reply via email to