Hi everyone,
I recently had the opportunity to work on the packaging of a custom XWiki WAR within a Docker image, while trying to rely as much as possible on the standard Docker build we provide in the platform *.
As part of this process, I observed that it was not that easy nor that efficient to replace the XWiki Standard WAR. There are basically two approaches :
- Either we need to re-build the whole docker image from scratch, starting from the base image of Tomcat.
- Or we need to take the image we want to build upon, remove the XWiki Standard WAR from this image, put the customized WAR, and put back the configuration files and the JDBC driver.
This second solution is a bit easier to maintain because some steps, such as the installation of LibreOffice are already taken care of in the standard image. However, it has the disadvantage of generating very big images, because docker images are made out of layers, each layer being a patch on top of its parent layer. We then have 3 big layers in our image :
- A first layer where the XS WAR is unzipped in the container
- A second layer where the XS WAR is removed from the container
- A third layer where the custom WAR is unzipped
I would have loved to just deploy sort of a “patch” on top of the XS WAR : adding and removing only the files that are relevant compared to what’s already in the XS WAR, however unfortunately I did not find any Maven artefact type that would be able to do that. If you have suggestions, I’ll be more than happy to know about them.
With the help of @gsautner, we tried to look at how it would be possible to make the build of the XWiki Docker images more modular. Much like the build of xwiki-platform-distribution-debian-common
which produce an intermediate artefact, we looked into how the build of XWiki’s Docker images could be modified to be re-usable downstream.
Currently, the build of the XWiki Docker image is roughly divided in 5 parts :
- The installation of prerequisites (LibreOffice + utilities needed to install the WAR)
- The installation of the WAR in Tomcat’s ROOT webapp + the installation of configuration files
- The installation of the JDBC driver
- Touch ups on the WAR (deployment of configuration files, update of the distribution ID)
- The installation of scripts for starting the docker image properly (such as
docker-entrypoint.sh
)
The two steps that are in italic (WAR install + touch ups on the WAR) are most probably the ones that would be valuable to override as part of projects deploying custom WARs in Docker images. With that in mind, one approach would be to update the build steps of our docker image to produce two intermediary images :
- The first intermediary image could contain the following steps :
- The installation of prerequisites (LibreOffice + utilities needed to install the WAR)
- The installation of scripts for starting the docker image properly (such as
docker-entrypoint.sh
)
- The second intermediary image would contain the setup of the database (there would be 1 intermediate image per database variant), with the following steps :
- The installation of the JDBC driver
- The installation of a default Hibernate configuration in
/etc/xwiki
- Finally, we would be left with two last steps that could be overridden more easily, by starting from the second intermediary image :
- The installation of the WAR in Tomcat’s ROOT webapp + the installation of configuration files
- Touch ups on the WAR (deployment of configuration files, update of the distribution ID)
WDYT ? Do you think that it is interesting to go forward with these changes, or does it bring too much complexity ? To note that, in that case, we would probably need to consider two changes to how we build the image :
- On one hand, deploy configuration files in
/etc/xwiki
instead of updating the WAR./etc/xwiki
could actually be defined as a volume. - On the other hand, deploy the JDBC drivers in the Tomcat lib folder, insetad of the WAR WEB-INF/lib folder.
Thanks,
Clément
* The project through which this work was done is accessible here ; the code related to the creation of a Docker image based on a different WAR is accessible here. We use jib to perform operations on top of base docker images as part of a Maven build.