0

I have a project structure like:

module-1
    pom.xml
    Dockerfile
module-2
    pom.xml
module-3
    pom.xml
module-4
    pom.xml
    Dockerfile
pom.xml

module-2 and module-3 are dependencies for module-1 and module-4

Now I want to deploy module-4 and module-1 independently. Now in my parent pom, I have added dockerfile-maven-plugin and added <skip> to true, while for both child projects I have skip false because I want to deploy them. However when I am trying to deploy module-1 its picking Dockerfile for module-4. So how should I configure my project so that each module pick it's respective Dockefile

My parent pom section looks like:

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <version>1.3.6</version>
    <configuration>
        <skip>true</skip>
    </configuration>
</plugin>

My child pom section for both child looks like :

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <version>1.3.6</version>
    <dependencies>
        <dependency>
            <groupId>jakarta.activation</groupId>
            <artifactId>jakarta.activation-api</artifactId>
            <version>1.2.2</version>
        </dependency>
    </dependencies>
    <configuration>
        <skip>false</skip>
        <repository>${docker.image.prefix}/${project.artifactId}</repository>
        <tag>${project.version}</tag>
        <useMavenSettingsForAuth>true</useMavenSettingsForAuth>
        <buildArgs>
            <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
        </buildArgs>
        <contextDirectory>${basedir}/</contextDirectory>
    </configuration>
</plugin>

Also , in the jenkins build I am running command : mvn -pl module-1,module-2,module-3 -am clean install

My Dockerfile for module-1 looks like

FROM openjdk:11-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
ADD ${JAR_FILE} module-1.jar
CMD java $JVM_OPTS -Djava.security.egd=file:/dev/./urandom -jar /module-1.jar

Need help

Anshul
  • 415
  • 4
  • 15
  • 1
    First I would suggest not to start with negative logic (skip in parent); Just define the version plugin general configuration in parent via pluginMangement. Add the execution in the module where you need it. That easier... Why are you adding a dependency to docker plugin? I doubt that the configuration of the JARFILE is really necessary..take a deep look into the docs about the defaults. (Maven is about Convention over configuration)... afterwards you should be able to do a simple `mvn clean install`(If really needed) `mvn clean verify` (should be enough) from root level – khmarbaise Jul 30 '21 at 11:35
  • @khmarbaise I need to deploy two modules module-1 and module-4 individually, however in the jenkins job in the reactor summary order, its trying to read to dockerfile for the module for which I don't want the image to be pushed. Can I configure that – Anshul Jul 30 '21 at 11:45
  • 1
    Configure the plugin where you need it...that's the point and not where you don't meaning in parent only version...in the modules where you need it bind it to the life cycle... – khmarbaise Jul 30 '21 at 15:15
  • @khmarbaise My solution is now running. So basically I did the way you suggested. Moreover I did this to skip the other deployments : mvn -pl module-1 dockerfile:build to read the module specific Dockerfile. Thanks for the suggestions though :) – Anshul Aug 02 '21 at 14:53

2 Answers2

0

What you describe works correctly under the following conditions:

Project structure:

project
├── module-1
│   ├── Dockerfile
│   ├── pom.xml
│   └── src
├── module-2
│   ├── pom.xml
│   └── src
├── module-3
│   ├── pom.xml
│   └── src
├── module-4
│   ├── Dockerfile
│   ├── pom.xml
│   └── src
└── pom.xml

Parent POM:

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>1.3.6</version>
                <dependencies>
                    <dependency>
                        <groupId>jakarta.activation</groupId>
                        <artifactId>jakarta.activation-api</artifactId>
                        <version>1.2.2</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <id>docker-build</id>
                        <phase>install</phase>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>docker-push</id>
                        <phase>deploy</phase>
                        <goals>
                            <goal>push</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <repository>${docker.image.prefix}/${project.artifactId}</repository>
                    <tag>${project.version}</tag>
                    <buildArgs>
                        <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                    </buildArgs>
                    <contextDirectory>${basedir}/</contextDirectory>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

Submodule POM:

<build>
    <plugins>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>dockerfile-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Build docker image for module 1 with command:

mvn -pl module-1,module-2,module-3 -am clean install

Output:

[INFO]  ---> 04ceb1feb02c
[INFO] Step 4/4 : ENTRYPOINT ["java", "-jar", "/app.jar"]
[INFO] 
[INFO]  ---> Running in 2d9866a14643
[INFO] Removing intermediate container 2d9866a14643
[INFO]  ---> ad16766ec096
[INFO] Successfully built ad16766ec096
[INFO] Successfully tagged ***/module-1:1.0-SNAPSHOT
[INFO] 
[INFO] Detected build of image with id ad16766ec096
[INFO] Building jar: ***/maven-docker/module-1/target/module-1-1.0-SNAPSHOT-docker-info.jar
[INFO] Successfully built ***/module-1:1.0-SNAPSHOT
[INFO]          ------------------------------------------------------------------------
[INFO] Reactor Summary for module-2 1.0-SNAPSHOT:
[INFO] 
[INFO] module-2 ............................................ SUCCESS [  0.797 s]
[INFO] module-3 ............................................ SUCCESS [  0.051 s]
[INFO] module-1 ............................................ SUCCESS [  5.019 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  6.016 s
[INFO] Finished at: 2021-07-30T14:47:53+03:00
[INFO] -----------------------------------------------------------------------

Used Dockerfile from module-1 because it has 4 steps (and module-4 has 2 steps).

Check docker image:

$ docker image list

Output:

REPOSITORY                     TAG              IMAGE ID       CREATED          SIZE
***/module-1               1.0-SNAPSHOT     ad16766ec096   16 minutes ago   456MB
...
Dmitry Rakovets
  • 557
  • 1
  • 6
  • 15
  • this configuration of parent pom won't require a Dockerfile under the parent project and only docker file of child would be required , right ?. I have added my dockerfile as well that is under each module – Anshul Jul 30 '21 at 12:27
  • Yes that's right. Added project structure to my answer. – Dmitry Rakovets Jul 30 '21 at 14:32
  • I have configured it the way you did, and now when I am trying to do this , it says Missing Dockerfile in context directory: /app/jenkins.. , I think its trying to find the Docker file around the parent pom directory – Anshul Jul 30 '21 at 15:27
  • my solution is now running. But we need to skip the deployment in parent pom. using true otherwise it would ask for Dockerfile, which is the default behaviour for docker plugin. Also in the child module we will override the skip with false in the configuration. But thank you so much for the detailed explanation as well :) – Anshul Aug 02 '21 at 14:50
  • This is good news!) I was glad to help as much as I could. Did I understand correctly? - `` was added to `` in parent POM but didn't work? - After you added `true` to `` in `` and it worked? – Dmitry Rakovets Aug 03 '21 at 01:19
  • Yes, I think by default docker maven plugin tries to read dockerfile near the parent pom, so we need to skip it . https://github.com/spotify/dockerfile-maven/issues/87 – Anshul Aug 03 '21 at 15:38
0

So, what we can do is for the parent pom :

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <version>1.3.6</version>
    <configuration>
        <skip>true</skip>
    </configuration>
</plugin>

In the child pom :

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <configuration>
        <skip>false</skip>
        <repository>${docker.image.prefix}/${project.artifactId}</repository>
        <tag>${project.version}</tag>
        <useMavenSettingsForAuth>true</useMavenSettingsForAuth>
        <buildArgs>
            <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
        </buildArgs>
        <contextDirectory>${project.basedir}/</contextDirectory>
    </configuration>
 </plugin>

Override skip to false

So now if we run mvn dockerfile:build , it would run docker plugin and read Dockerfile for each sub-module . However if you want to apply this to a specific module , you can run mvn -pl your-module dockerfile:build so the other modules that we don't want will not run in the reactor summary.

Also , you can add the executions in the child where you want

Anshul
  • 415
  • 4
  • 15