Move from javax to jakarta with Apache TomEE 9 (Part 3): dockerize it
In two previous post we built a jakarta TomEE distribution and migrated an application to TomEE. The two missing pieces are:
- The testing layer
- The final packaging.
The testing reuses what we saw by making libraries jakarta friendly or using TomEE Remote in your test there is nothing more than using the distribution you built. So I will not detail the testing for now - until I get a lot of requests to do it ;).
The packaging is important since it is what will deliver your application. Since the usage of jakarta likely means it is a new application or an application you invest in - otherwise you can stick to javax for years, it also likely means you will deploy it in docker.
So at current stage, we have a ready to run TomEE with our application in target/tomee/standalone and we want to put it in a docker container. You can write a Dockerfile but I encourage you to use JIB. This has the advantage to be very maven friendly but also to not require the docker daemon to push an image on a registry which is great on CI.
Our build will put our tomee instance in /opt/application, use a JRE 11 as base image and launch TomEE in waiting mode (to let a kill on the container kill the instance).
The base will look like:
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>2.7.0</version> <!-- 1 -->
<executions>
<execution>
<id>standalone</id>
<phase>none</phase> <!-- 2 -->
<configuration>
<extraDirectories>
<paths>
<path> <!-- 3 -->
<from>${project.build.directory}/tomee/standalone</from>
<into>/opt/application</into>
</path>
</paths>
</extraDirectories>
<from> <!-- 4 -->
<image>adoptopenjdk/openjdk11:jre-11.0.9_11.1-alpine@sha256:58254737530df7f7e7acfe3e7538a027f898ac05accd2e15adcef34d5a33ae72</image>
</from>
<to> <!-- 5 -->
<image>rmannibucau/app-jakarta-demo</image>
</to>
<container>
<!-- 6 -->
<appRoot>/opt/application</appRoot>
<workingDirectory>/opt/application</workingDirectory>
<!-- 7 -->
<entrypoint>
<entry>sh</entry>
<entry>/opt/application/bin/catalina.sh</entry>
<entry>run</entry>
</entrypoint>
<ports> <!-- 8 -->
<port>8080</port>
</ports>
</container>
</configuration>
</execution>
</executions>
</plugin>
- We configure jib plugin,
- We define an execution to build our docker image - as in previous posts we make this callable explicitly but not bound to any phase,
- We require jib to copy our tomee distribution to /opt/application in the container,
- We use OpenJDK11 (jre) as base image. The sha is optional but ensures we use the image we expect since docker images are not immutables,
- We define the target name of our image (without more configuration it will be tagged latest but you can explicit the version),
- We define the application and container working directory to the application folder we chose,
- We define our entry point to be tomcat catalina.sh script and we execute run option to ensure the prcess is aligned on the container lifecycle,
- Finally we define that our TomEE we use the port 8080.
Note: without any server.xml tuning, AJP port will be used on port 8009. It is almost never useful with docker so we don't define it and you can even define a sever.xml without this connector in src/main/tomee/conf if desired.
If you run the following command, JIB will create your image and load it in your local docker registry (replace dockerBuild by build and add a registry host as prefix of your image name and you will push it remotely):
mvn jib:dockerBuild@standalone
In other words, it means you can now launch your application running:
docker run -p 8080:8080 rmannibucau/app-jakarta-demo
Great no? Actually not that much. JIB is opiniated and is integrated with JAR and WAR so it added your application files in the container image whereas you already created a TomEE/Tomcat oriented layout JIB does not know about.
To drop the "leaking" files, you can use JIB filter extension which enables to delete files from layers.
TIP: it also enables to reorganize layers so you could put all TomEE in a layer and your application in another layer. Assuming your application moves more than TomEE it will make the docker image update faster most of the time.
Here is how to remove unneeded file - we will even remove the distribution unneeded files as the README for example:
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>2.7.0</version>
<executions>
<execution>
<id>standalone</id>
<phase>none</phase>
<configuration>
<!-- same configuration as before, omitted for brievity -->
<pluginExtensions>
<pluginExtension> <!-- 1 -->
<implementation>com.google.cloud.tools.jib.maven.extension.layerfilter.JibLayerFilterExtension</implementation>
<configuration implementation="com.google.cloud.tools.jib.maven.extension.layerfilter.Configuration">
<filters>
<!-- 2 -->
<filter>
<glob>/opt/application/*.txt</glob>
</filter>
<filter>
<glob>/opt/application/*.md</glob>
</filter>
<filter>
<glob>/opt/application/LICENSE</glob>
</filter>
<filter>
<glob>/opt/application/NOTICE</glob>
</filter>
<filter>
<glob>/opt/application/RELEASE-NOTES</glob>
</filter>
<filter>
<glob>/opt/application/RUNNING.txt</glob>
</filter>
<!-- 3 -->
<filter>
<glob>/opt/application/META-INF/**</glob>
</filter>
<filter>
<glob>/opt/application/META-INF</glob>
</filter>
<!-- 4 -->
<filter>
<glob>/opt/application/WEB-INF/**</glob>
</filter>
<filter>
<glob>/opt/application/WEB-INF</glob>
</filter>
<filter>
<glob>/opt/application/classpath/**</glob>
</filter>
<filter>
<glob>/opt/application/classpath</glob>
</filter>
<filter>
<glob>/opt/application/resources/**</glob>
</filter>
<filter>
<glob>/opt/application/resources</glob>
</filter>
<filter> <!-- 5 -->
<glob>/opt/application/index*</glob>
</filter>
</filters>
</configuration>
</pluginExtension>
</pluginExtensions>
</configuration>
</execution>
</executions>
<dependencies>
<dependency> <!-- 6 -->
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-layer-filter-extension-maven</artifactId>
<version>0.1.0</version>
</dependency>
</dependencies>
</plugin>
- We add to previous configuration a plugin extenson of jib;
- We configure the filter extension to "filter" all the Tomcat undesired files (text files mainly). JIB filter extension removes the file when there is no target layer in <filter> configuration which is what we use there.
- JIB adds webapp and resources files so we drop resources first. Note that due to JVM glob implementation we must add two expressions to drop a folder, one to empty it and one to drop the folder itself.
- Same thing than for resources (3) but for webapp directory (src/main/webapp).
- Note that if you have folders or custom files in webapp directory you can also need to filter them here like this index file for example.
- Finally we ensure the jib filter extension is available for the plugin.
Now if we run back the jib command we will get a clean docker image.
From the same author:
In the same category: