You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2019/04/17 12:44:55 UTC

[karaf] branch karaf-4.2.x updated: [KARAF-6154] Add karaf docker example with dynamic & static distributions

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

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


The following commit(s) were added to refs/heads/karaf-4.2.x by this push:
     new 5a213b8  [KARAF-6154] Add karaf docker example with dynamic & static distributions
5a213b8 is described below

commit 5a213b833e08a781514699744294fdfc253c78a7
Author: Jean-Baptiste Onofré <jb...@apache.org>
AuthorDate: Wed Mar 6 18:46:46 2019 +0100

    [KARAF-6154] Add karaf docker example with dynamic & static distributions
---
 examples/karaf-docker-example/README.md            | 339 +++++++++++++++++++++
 .../karaf-docker-example-app/pom.xml               |  78 +++++
 .../karaf/examples/docker/ExampleServlet.java      |  55 ++++
 .../karaf-docker-example-dynamic-dist/pom.xml      | 160 ++++++++++
 .../k8s/karaf-docker-example-static-dist.yaml      |  31 ++
 .../karaf-docker-example-static-dist/pom.xml       | 129 ++++++++
 examples/karaf-docker-example/pom.xml              |  41 +++
 examples/pom.xml                                   |   1 +
 .../org/apache/karaf/tooling/DockerfileMojo.java   |   5 +-
 9 files changed, 838 insertions(+), 1 deletion(-)

diff --git a/examples/karaf-docker-example/README.md b/examples/karaf-docker-example/README.md
new file mode 100644
index 0000000..19b85e0
--- /dev/null
+++ b/examples/karaf-docker-example/README.md
@@ -0,0 +1,339 @@
+<!--
+    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.
+-->
+
+# Apache Karaf Docker example
+
+## Abstract
+
+This example is a complete example how to easily create a Karaf powered application and package as a docker image, ready
+to run anyway.
+
+This example provides two kind of distributions:
+
+* static distribution is very similar to Spring Boot approach, but supporting all Karaf powerful features.  The Karaf static (almost immutable) is a resolution performed at build time, and
+we start all features (bundles set) at startup without the resolver. It's super fast, light and straight forward.
+* dynamic distribution is applications container approach. It's the same kind of distribution as the Apache Karaf "vanilla" one: Karaf starts with a set of "boot" features. Then, you can deploy
+new applications (at runtime) on the runtime instance.
+
+## Artifacts
+
+The project example is composed of three modules:
+
+* `karaf-docker-example-app` is a regular Karaf application module. For this example, we implement a Servlet. We use the Karaf Maven plugin to automatically create a features XML that we will use for the distribution.
+* `karaf-docker-example-static-dist` doesn't contain any code, just a `pom.xml`. This module creates a Karaf static distribution (almost immutable) ready to run, provide a turnkey Dockerfile and optionally create the corresponding Docker image.
+* `karaf-docker-example-dynamic-dist` doesn't contain any code, just a `pom.xml`. This modules creates a Karaf dynamic distribution (applications container) ready to run, provide a turnkey Dockerfile and optionally create the corresponding Docker image.
+
+### App
+
+The `karaf-docker-example-app` is a regular Karaf application (packaged as a bundle). It uses SCR annotation to register
+a `Servlet` service that the `http-whiteboard` feature will deploy.
+
+It's possible to create a bunch of `app` modules like this one and include in several runtime.
+
+To include the apps in the runtime (dist), we need a features XML file.
+
+In the example, we simply use the Karaf Maven plugin `features-generate-descriptor` goal to automatically create the
+features XML.
+
+### Runtimes (distributions)
+
+The `dist` modules create Karaf runtimes embedding the app.
+
+#### Dynamic distribution
+
+The `dynamic` distribution is the approach used by Apache Karaf vanilla distribution: it's a applications container approach.
+
+You start the Karaf instance with "boot" applications, and then you can (at runtime) deploy new applications in the running instance. You can also update
+the configuration, undeploy applications, etc at runtime.
+
+We use the `karaf-maven-plugin` to create the distribution automatically:
+
+1. the `assembly` goal creates the Karaf runtime filesystem, using the dependencies from the `pom.xml`
+2. the `archive` goal creates an archive (tar.gz, zip) containing the Karaf runtime filesystem
+3. the `dockerfile` goal creates a Dockerfile ready to create a Karaf Docker image
+4. optionally, the `docker` goal can take the Dockerfile and directly use `docker` to create the Karaf Docker image.
+
+#### Static distribution
+
+On the other hand `static` distribution is a completely different approach where the resolution is made at build time.
+
+We use the `karaf-maven-plugin` to create the distribution automatically:
+
+1. the `assembly` goal creates the Karaf runtime filesystem, using the dependencies from the `pom.xml`
+2. the `archive` goal creates an archive (tar.gz, zip) containing the Karaf runtime filesystem
+3. the `dockerfile` goal creates a Dockerfile ready to create a Karaf Docker image
+4. optionally, the `docker` goal can take the Dockerfile and directly use `docker` to create the Karaf Docker image.
+
+The difference between dynamic and static distributions is just the configuration of the project and the `karaf-maven-plugin`.
+
+## Build
+
+The build uses Apache Maven. Simply use:
+
+```
+$ mvn clean install
+```
+
+You will find the runtime in `karaf-docker-example-dist/target` folder (tar.gz and zip), and also the `Dockerfile`.
+
+You can eventually directly create the Docker image using the `docker` profile (assuming `docker` is installed on your machine):
+
+```
+$ mvn clean install -Pdocker
+```
+
+## Usage
+
+### Static
+
+Locally you can use `karaf-docker-example-static-dist/target/assembly`, with the `karaf run`:
+
+```
+$ karaf-docker-example-static-dist/target/assembly/bin/karaf run
+```
+
+You can also use the zip or tar.gz archive:
+
+```
+$ cd karaf-docker-example-static-dist/target
+$ tar zxvf karaf-docker-example-static-dist-*.tar.gz
+$ cd karaf-docker-example-static-dist*/bin
+$ ./karaf run
+```
+
+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
+ ---> d60154a7d9b2
+Step 2/7 : ENV KARAF_INSTALL_PATH /opt
+ ---> Using cache
+ ---> ff77d7ccbfe3
+Step 3/7 : ENV KARAF_HOME $KARAF_INSTALL_PATH/apache-karaf
+ ---> Using cache
+ ---> 0ebb21305f76
+Step 4/7 : ENV PATH $PATH:$KARAF_HOME/bin
+ ---> Using cache
+ ---> 31bbe4c15205
+Step 5/7 : COPY assembly $KARAF_HOME
+ ---> Using cache
+ ---> a9a88b63244e
+Step 6/7 : EXPOSE 8101 1099 44444 8181
+ ---> Using cache
+ ---> 274550b95b48
+Step 7/7 : CMD ["karaf", "run"]
+ ---> Using cache
+ ---> 7dbc9b63c058
+Successfully built 7dbc9b63c058
+Successfully tagged mykaraf:latest
+```
+
+If you used the `docker` profile (`-Pdocker`) during the Maven build, you have the `karaf` docker image:
+
+```
+$ cd karaf-docker-example-static-dist
+$ mvn clean install -Pdocker
+```
+
+```
+$ docker images
+REPOSITORY                                 TAG                 IMAGE ID            CREATED             SIZE
+karaf-docker-example-static-dist           latest              226223b45024        6 seconds ago       463MB
+```
+
+You can use the docker image very easily (wherever you want):
+
+```
+$ docker run --name mykaraf -p 8181:8181 mykaraf
+```
+
+You can start the docker container in daemon mode:
+
+```
+$ docker run --name mykaraf -p 8181:8181 -d mykaraf
+```
+
+We can see our docker container running:
+
+```
+$ docker ps
+CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                                     NAMES
+d5f14a025286        karaf               "karaf run"         4 minutes ago       Up 4 minutes        1099/tcp, 8101/tcp, 8181/tcp, 44444/tcp   mykaraf
+```
+
+Then you can see the logs using `docker logs`:
+
+```
+$ docker logs mykaraf
+karaf: Ignoring predefined value for KARAF_HOME
+Mar 21, 2019 11:09:54 AM org.apache.karaf.main.Main launch
+INFO: Installing and starting initial bundles
+Mar 21, 2019 11:09:54 AM org.apache.karaf.main.Main launch
+INFO: All initial bundles installed and set to start
+Mar 21, 2019 11:09:54 AM org.apache.karaf.main.Main$KarafLockCallback lockAcquired
+INFO: Lock acquired. Setting startlevel to 100
+11:09:54.871 INFO  [FelixStartLevel] Logging initialized @811ms to org.eclipse.jetty.util.log.Slf4jLog
+11:09:54.882 INFO  [FelixStartLevel] EventAdmin support is not available, no servlet events will be posted!
+11:09:54.883 INFO  [FelixStartLevel] LogService support enabled, log events will be created.
+11:09:54.885 INFO  [FelixStartLevel] Pax Web started
+11:09:55.110 INFO  [paxweb-config-1-thread-1] No ALPN class available
+11:09:55.111 INFO  [paxweb-config-1-thread-1] HTTP/2 not available, creating standard ServerConnector for Http
+11:09:55.127 INFO  [paxweb-config-1-thread-1] Pax Web available at [0.0.0.0]:[8181]
+11:09:55.131 INFO  [paxweb-config-1-thread-1] Binding bundle: [org.ops4j.pax.web.pax-web-extender-whiteboard [48]] to http service
+11:09:55.143 INFO  [paxweb-config-1-thread-1] Binding bundle: [org.apache.karaf.examples.karaf-docker-example-app [15]] to http service
+11:09:55.153 INFO  [paxweb-config-1-thread-1] will add org.eclipse.jetty.websocket.server.NativeWebSocketServletContainerInitializer to ServletContainerInitializers
+11:09:55.154 INFO  [paxweb-config-1-thread-1] added ServletContainerInitializer: org.eclipse.jetty.websocket.server.NativeWebSocketServletContainerInitializer
+11:09:55.154 INFO  [paxweb-config-1-thread-1] will add org.apache.jasper.servlet.JasperInitializer to ServletContainerInitializers
+11:09:55.155 INFO  [paxweb-config-1-thread-1] Skipt org.apache.jasper.servlet.JasperInitializer, because specialized handler will be present
+11:09:55.155 INFO  [paxweb-config-1-thread-1] will add org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer to ServletContainerInitializers
+11:09:55.207 INFO  [paxweb-config-1-thread-1] added ServletContainerInitializer: org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer
+11:09:55.241 INFO  [paxweb-config-1-thread-1] registering context DefaultHttpContext [bundle=org.apache.karaf.examples.karaf-docker-example-app [15], contextID=default], with context-name:
+11:09:55.251 INFO  [paxweb-config-1-thread-1] registering JasperInitializer
+11:09:55.282 INFO  [paxweb-config-1-thread-1] No DecoratedObjectFactory provided, using new org.eclipse.jetty.util.DecoratedObjectFactory[decorators=1]
+11:09:55.354 INFO  [paxweb-config-1-thread-1] DefaultSessionIdManager workerName=node0
+11:09:55.354 INFO  [paxweb-config-1-thread-1] No SessionScavenger set, using defaults
+11:09:55.355 INFO  [paxweb-config-1-thread-1] node0 Scavenging every 600000ms
+11:09:55.364 INFO  [paxweb-config-1-thread-1] Started HttpServiceContext{httpContext=DefaultHttpContext [bundle=org.apache.karaf.examples.karaf-docker-example-app [15], contextID=default]}
+11:09:55.369 INFO  [paxweb-config-1-thread-1] jetty-9.4.12.v20180830; built: 2018-08-30T13:59:14.071Z; git: 27208684755d94a92186989f695db2d7b21ebc51; jvm 1.8.0_181-8u181-b13-2~deb9u1-b13
+11:09:55.403 INFO  [paxweb-config-1-thread-1] Started default@437b18f2{HTTP/1.1,[http/1.1]}{0.0.0.0:8181}
+11:09:55.403 INFO  [paxweb-config-1-thread-1] Started @1347ms
+11:09:55.405 INFO  [paxweb-config-1-thread-1] Binding bundle: [org.apache.karaf.http.core [16]] to http service
+```
+
+Now, in a web brower, you can test the Servlet using [http://localhost:8181/servlet-example].
+
+[NOTE]
+===
+Update the host if you run the container somewhere else, like on a cloud.
+===
+
+You can push this docker image wherever you want, on a cloud provider for instance.
+
+We can see the logs updated:
+
+```
+$ docker logs mykaraf
+...
+11:23:39.064 INFO  [qtp810811468-37] Client 172.17.0.1 request received on http://localhost:8181/servlet-example
+```
+
+### Dynamic
+
+Locally you can use `karaf-docker-example-dynamic-dist/target/assembly`, with the `karaf`:
+
+```
+$ karaf-docker-example-dynamic-dist/target/assembly/bin/karaf
+```
+
+You can also use the zip or tar.gz archive:
+
+```
+$ cd karaf-docker-example-dynamic-dist/target
+$ tar zxvf karaf-docker-example-dynamic-dist-*.tar.gz
+$ cd karaf-docker-example-dynamic-dist*/bin
+$ ./karaf
+```
+
+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
+ ---> 19c48cc84cc6
+Step 2/7 : ENV KARAF_INSTALL_PATH /opt
+ ---> Running in 8a9a42db2395
+Removing intermediate container 8a9a42db2395
+ ---> 45f002fb0def
+Step 3/7 : ENV KARAF_HOME $KARAF_INSTALL_PATH/apache-karaf
+ ---> Running in c25e2a10d78e
+Removing intermediate container c25e2a10d78e
+ ---> ce1f0d7bdb0a
+Step 4/7 : ENV PATH $PATH:$KARAF_HOME/bin
+ ---> Running in 0fd126ff3a5f
+Removing intermediate container 0fd126ff3a5f
+ ---> 3ac6aaa5b072
+Step 5/7 : COPY assembly $KARAF_HOME
+ ---> 9a6a003d9845
+Step 6/7 : EXPOSE 8101 1099 44444 8181
+ ---> Running in 8e24a41487fb
+Removing intermediate container 8e24a41487fb
+ ---> 5643c771527c
+Step 7/7 : CMD ["karaf"]
+ ---> Running in 0e35ac21467d
+Removing intermediate container 0e35ac21467d
+ ---> d0cbfa94125c
+Successfully built d0cbfa94125c
+Successfully tagged mykaraf:latest
+
+```
+
+If you used the `docker` profile (`-Pdocker`) during the Maven build, you have the `karaf` docker image:
+
+```
+$ cd karaf-docker-example-dynamic-dist
+$ mvn clean install -Pdocker
+```
+
+```
+$ docker images
+REPOSITORY                                 TAG                 IMAGE ID            CREATED              SIZE
+karaf-docker-example-dynamic-dist          latest              38628803d8b2        3 seconds ago        479MB
+```
+
+You can use the docker image very easily (wherever you want):
+
+```
+$ docker run -i -t --name mykaraf -p 8181:8181 mykaraf
+karaf: Ignoring predefined value for KARAF_HOME
+        __ __                  ____      
+       / //_/____ __________ _/ __/      
+      / ,<  / __ `/ ___/ __ `/ /_        
+     / /| |/ /_/ / /  / /_/ / __/        
+    /_/ |_|\__,_/_/   \__,_/_/         
+
+  Apache Karaf (4.2.5)
+
+Hit '<tab>' for a list of available commands
+and '[cmd] --help' for help on a specific command.
+Hit '<ctrl-d>' or type 'system:shutdown' or 'logout' to shutdown Karaf.
+
+karaf@root()>  
+```
+
+We started here with the shell console. You can directly type Karaf shell commands here and interact the running
+Karaf instance. 
+
+[NOTE]
+==
+You can also override the startup command to use `karaf server`.
+==
+
+Now, in a web brower, you can test the Servlet using [http://localhost:8181/servlet-example].
+
+we can see the request performed on our running Karaf instance:
+
+```
+karaf@root()> log:display
+08:43:36.497 INFO [qtp1056947824-99] Client 172.17.0.1 request received on http://localhost:8181/servlet-example
+```
\ No newline at end of file
diff --git a/examples/karaf-docker-example/karaf-docker-example-app/pom.xml b/examples/karaf-docker-example/karaf-docker-example-app/pom.xml
new file mode 100644
index 0000000..e8612d9
--- /dev/null
+++ b/examples/karaf-docker-example/karaf-docker-example-app/pom.xml
@@ -0,0 +1,78 @@
+<?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">
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf.examples</groupId>
+        <artifactId>karaf-docker-example</artifactId>
+        <version>4.2.5-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>karaf-docker-example-app</artifactId>
+    <name>Apache Karaf :: Examples :: Docker :: Sample Application</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <version>3.1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+            <version>6.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.karaf.tooling</groupId>
+                <artifactId>karaf-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>features-generate-descriptor</goal>
+                        </goals>
+                        <configuration>
+                            <includeProjectArtifact>true</includeProjectArtifact>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/examples/karaf-docker-example/karaf-docker-example-app/src/main/java/org/apache/karaf/examples/docker/ExampleServlet.java b/examples/karaf-docker-example/karaf-docker-example-app/src/main/java/org/apache/karaf/examples/docker/ExampleServlet.java
new file mode 100644
index 0000000..97a3e9f
--- /dev/null
+++ b/examples/karaf-docker-example/karaf-docker-example-app/src/main/java/org/apache/karaf/examples/docker/ExampleServlet.java
@@ -0,0 +1,55 @@
+/*
+ *  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.examples.docker;
+
+import org.osgi.service.component.annotations.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+@Component(
+        property = { "alias=/servlet-example", "servlet-name=Example"}
+)
+public class ExampleServlet extends HttpServlet implements Servlet {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(ExampleServlet.class);
+
+    @Override
+    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+        LOGGER.info("Client " + request.getRemoteAddr() + " request received on " + request.getRequestURL());
+
+        try (PrintWriter writer = response.getWriter()) {
+            writer.println("<html>");
+            writer.println("<head>");
+            writer.println("<title>Example</title>");
+            writer.println("</head>");
+            writer.println("<body align='center'>");
+            writer.println("<h1>Example Servlet</h1>");
+            writer.println("</body>");
+            writer.println("</html>");
+        }
+    }
+
+}
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
new file mode 100644
index 0000000..fa89c48
--- /dev/null
+++ b/examples/karaf-docker-example/karaf-docker-example-dynamic-dist/pom.xml
@@ -0,0 +1,160 @@
+<?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">
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf.examples</groupId>
+        <artifactId>karaf-docker-example</artifactId>
+        <version>4.2.5-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>karaf-docker-example-dynamic-dist</artifactId>
+    <name>Apache Karaf :: Examples :: Docker :: Dynamic Distribution</name>
+    <packaging>pom</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>framework</artifactId>
+            <type>kar</type>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>framework</artifactId>
+            <classifier>features</classifier>
+            <type>xml</type>
+            <scope>runtime</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>standard</artifactId>
+            <classifier>features</classifier>
+            <type>xml</type>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.examples</groupId>
+            <artifactId>karaf-docker-example-app</artifactId>
+            <type>xml</type>
+            <classifier>features</classifier>
+            <version>${project.version}</version>
+            <scope>runtime</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.karaf.tooling</groupId>
+                <artifactId>karaf-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>process-resources</id>
+                        <phase>process-resources</phase>
+                        <goals>
+                            <goal>assembly</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>package</id>
+                        <goals>
+                            <goal>archive</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>dockerfile</id>
+                        <goals>
+                            <goal>dockerfile</goal>
+                        </goals>
+                        <configuration>
+                            <command>["karaf"]</command>
+                        </configuration>
+                    </execution>
+                </executions>
+                <configuration>
+                    <installedFeatures>
+                        <feature>wrapper</feature>
+                        <feature>aries-blueprint</feature>
+                        <feature>shell-compat</feature>
+                    </installedFeatures>
+                    <startupFeatures>
+                        <feature>eventadmin</feature>
+                    </startupFeatures>
+                    <bootFeatures>
+                        <feature>wrap</feature>
+                        <feature>shell</feature>
+                        <feature>feature</feature>
+                        <feature>jaas</feature>
+                        <feature>ssh</feature>
+                        <feature>management</feature>
+                        <feature>bundle</feature>
+                        <feature>config</feature>
+                        <feature>deployer</feature>
+                        <feature>diagnostic</feature>
+                        <feature>feature</feature>
+                        <feature>instance</feature>
+                        <feature>kar</feature>
+                        <feature>log</feature>
+                        <feature>package</feature>
+                        <feature>service</feature>
+                        <feature>system</feature>
+                        <feature>scr</feature>
+                        <feature>http-whiteboard</feature>
+                        <feature>karaf-docker-example-app</feature>
+                    </bootFeatures>
+                    <libraries>
+                    </libraries>
+                    <javase>1.8</javase>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>docker</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.karaf.tooling</groupId>
+                        <artifactId>karaf-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>docker-image</id>
+                                <goals>
+                                    <goal>docker</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                        <configuration>
+                            <imageName>${project.artifactId}</imageName>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+</project>
\ No newline at end of file
diff --git a/examples/karaf-docker-example/karaf-docker-example-static-dist/k8s/karaf-docker-example-static-dist.yaml b/examples/karaf-docker-example/karaf-docker-example-static-dist/k8s/karaf-docker-example-static-dist.yaml
new file mode 100644
index 0000000..03cf23f
--- /dev/null
+++ b/examples/karaf-docker-example/karaf-docker-example-static-dist/k8s/karaf-docker-example-static-dist.yaml
@@ -0,0 +1,31 @@
+# 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.
+apiVersion: v1
+kind: Pod
+metadata:
+  name: karaf-docker-example-static-dist
+spec:
+  containers:
+    - name: karaf-docker-example-static-dist-ctr
+      image: karaf:latest
+      resources:
+        limits:
+          memory: "500Mi"
+        requests:
+          memory: "250Mi"
+      command: ["karaf", "run"]
+      args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]
\ No newline at end of file
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
new file mode 100644
index 0000000..2326285
--- /dev/null
+++ b/examples/karaf-docker-example/karaf-docker-example-static-dist/pom.xml
@@ -0,0 +1,129 @@
+<?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">
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+       <groupId>org.apache.karaf.examples</groupId>
+        <artifactId>karaf-docker-example</artifactId>
+        <version>4.2.5-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>karaf-docker-example-static-dist</artifactId>
+    <name>Apache Karaf :: Examples :: Docker :: Static Distribution</name>
+    <packaging>pom</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>static</artifactId>
+            <type>kar</type>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>standard</artifactId>
+            <classifier>features</classifier>
+            <type>xml</type>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.services</groupId>
+            <artifactId>org.apache.karaf.services.staticcm</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.examples</groupId>
+            <artifactId>karaf-docker-example-app</artifactId>
+            <type>xml</type>
+            <classifier>features</classifier>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.karaf.tooling</groupId>
+                <artifactId>karaf-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>process-resources</id>
+                        <phase>process-resources</phase>
+                        <goals>
+                            <goal>assembly</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>package</id>
+                        <goals>
+                            <goal>archive</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>dockerfile</id>
+                        <goals>
+                            <goal>dockerfile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <startupFeatures>
+                        <startupFeature>static-framework</startupFeature>
+                        <startupFeature>scr</startupFeature>
+                        <startupFeature>http-whiteboard</startupFeature>
+                        <startupFeature>karaf-docker-example-app</startupFeature>
+                    </startupFeatures>
+                    <framework>static</framework>
+                    <useReferenceUrls>true</useReferenceUrls>
+                    <environment>static</environment>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>docker</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.karaf.tooling</groupId>
+                        <artifactId>karaf-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>docker-image</id>
+                                <goals>
+                                    <goal>docker</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                        <configuration>
+                            <imageName>${project.artifactId}</imageName>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+</project>
diff --git a/examples/karaf-docker-example/pom.xml b/examples/karaf-docker-example/pom.xml
new file mode 100644
index 0000000..309edf5
--- /dev/null
+++ b/examples/karaf-docker-example/pom.xml
@@ -0,0 +1,41 @@
+<?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">
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf.examples</groupId>
+        <artifactId>apache-karaf-examples</artifactId>
+        <version>4.2.5-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>karaf-docker-example</artifactId>
+    <name>Apache Karaf :: Examples :: Docker</name>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>karaf-docker-example-app</module>
+        <module>karaf-docker-example-static-dist</module>
+        <module>karaf-docker-example-dynamic-dist</module>
+    </modules>
+
+</project>
\ No newline at end of file
diff --git a/examples/pom.xml b/examples/pom.xml
index 793e969..3930c30 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -42,6 +42,7 @@
         <module>karaf-command-example</module>
         <module>karaf-config-example</module>
         <module>karaf-deployer-example</module>
+        <module>karaf-docker-example</module>
         <module>karaf-dump-example</module>
         <!-- <module>karaf-encryption-example</module> -->
         <module>karaf-http-resource-example</module>
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 071e0a8..f0edcd8 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
@@ -37,6 +37,9 @@ public class DockerfileMojo extends MojoSupport {
     @Parameter(defaultValue = "${project.build.directory}/assembly")
     private File assembly;
 
+    @Parameter(defaultValue = "[\"karaf\", \"run\"]")
+    private String command;
+
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
         getLog().info("Creating Dockerfile");
@@ -49,7 +52,7 @@ public class DockerfileMojo extends MojoSupport {
             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 [\"karaf\", \"run\"]").append("\n");
+            buffer.append("CMD ").append(command).append("\n");
             try (FileWriter writer = new FileWriter(dockerFile)) {
                 writer.write(buffer.toString());
             }