I've successfully created a docker image with fabric8 plugin, using a custom Dockerfile, for a Servlet WebApp.
The image is based on tomcat, and so I need to put the app in tomcat/webapps
To optimize the image I'm not inserting the war directly, but instead the expanded content of it, in two separate layers: one for WEB-INF\lib
and one with all other.
Image Layers:
- WEB-INF\classes and resources
- WEB-INF\lib
- tomcat (base layer)
this way if I create a new version but the libs are the same as the old one, the remote server only need to pull the app layer
I'm copying the content of the war from the folder "target/MyProject" generated by maven-war-plugin and from which it then creates the "MyProject.war"
But this folder does not contains the META-INF\MANIFEST.MF
file (is it created directly in the war?)
Is there a way to create the manifest file in some folder so I can copy it into the docker image?
Here part of the pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<archive>
<manifestEntries>
/*...*/
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.30.0</version>
<extensions>true</extensions>
<configuration>
<images>
<image>
<name>${project.version}-${docker-image-tag}</name>
<build>
<contextDir>${project.basedir}/src/main/docker</contextDir>
<assembly>
<name>target</name>
<inline>
<fileSets>
<fileSet>
<directory>${project.build.directory}/${project.build.finalName}</directory>
<outputDirectory>slimWar</outputDirectory>
<excludes>
<exclude>WEB-INF\lib\**</exclude>
</excludes>
<useDefaultExcludes>false</useDefaultExcludes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/${project.build.finalName}</directory>
<outputDirectory>libs</outputDirectory>
<includes>
<include>WEB-INF\lib\**</include>
</includes>
<useDefaultExcludes>false</useDefaultExcludes>
</fileSet>
</fileSets>
</inline>
</assembly>
</build>
</image>
</images>
</configuration>
</plugin>
I've found a solution, in case someone will face this problem. The trick is to add and decompress the war directly, but doing so will result in a layer with the war and one (or more) with the extracted files
To solve this we can use docker multi-stage build:
pom.xml
<build>
<contextDir>${project.basedir}/src/main/docker/${docker-contextDir}</contextDir>
<assembly>
<descriptorRef>rootWar</descriptorRef>
</assembly>
</build>
this will add the artifact as ROOT.war in the /maven directory (inside the image)
Dockerfile
FROM busybox AS unzippedWar
ADD /maven/ROOT.war /
RUN mkdir -p /war/slimWar
RUN mkdir -p /war/libs
RUN unzip -qq /ROOT.war -d /war/slimWar
RUN mkdir -p /war/libs/WEB-INF/lib
RUN mv /war/slimWar/WEB-INF/lib/* /war/libs/WEB-INF/lib
FROM tomcat:9-jdk8-openjdk-slim
RUN rm -rf /usr/local/tomcat/webapps/*
COPY --from=unzippedWar /war/libs /usr/local/tomcat/webapps/ROOT/
COPY --from=unzippedWar /war/slimWar /usr/local/tomcat/webapps/ROOT/
EXPOSE 80
and this time the MANIFEST.MF will be there
to be picky, the only downside (but it's hardly a problem) is the leftover intermediate image that need to be removed manually, as explained here.