Building or extending Jahia images

November 14, 2023

Jahia docker images have been designed to be easily extendable and/or re-buildable, allowing our customers to use an image matching precisely the need of their production environment as well as supporting development and discovery use cases.

Extend, build, or both?

When it comes to using our images in production with additional modules or functionalities (including some you might have developed or some built by Jahia partners), two options are available:

  • You can extend our Docker image at runtime by means of our provisioning API. This will allow you to automatically perform a set of actions during Jahia startup (such as installing additional modules). 
  • You can build your own Docker image, using a Jahia Docker release as a base. This approach allows you to pre-package in a single image all of the assets and configurations you know will be applied every time this Docker image is starting.

Of course, you also have the ability to use both techniques, building a new image and extending it at runtime.

Extending docker images

Using our provisioning API, Jahia can perform a set of actions at runtime (such as installing a module, applying a configuration, ...).

This approach is the easiest to get started with and has the benefit of facilitating maintenance and migrations, but extending the image at runtime means that every time you run the image, the same set of actions will be performed. 

The provisioning script syntax is compatible across versions, and except if you perform actions bound to a particular version of Jahia (or a particular version of its dependencies), the content of the script itself should also be compatible across Jahia versions.

Three methods are available to provision Jahia at runtime:

  • By submitting a script to Jahia's provisioning API
  • By copying a script to the right location on Jahia's filesystem (docker cp)
  • By providing a link to a startup script

Using Jahia provisioning API

This method is detailed in greater details in a dedicated section of the Academy.

The benefit of this method is the ability to know when the script has completed its execution (after receiving a response from the API), but it also means you need to set-up some tooling to identify when Jahia is ready to receive the API call.

You can see an example of this configuration in this tutorial.

Using "docker cp" to copy a provisioning script

This method requires direct access to the filesystem, using this technique, one would start a docker container and copy the provisioning script to the right location on Jahia's filesystem within the container.

Assuming you have a provisioning script located in /tmp/my-script.yml

docker run -p 8080:8080 --name my_jahia jahia/jahia:8.0.3.0 
docker cp /tmp/my-script.yml my_jahia:/usr/local/tomcat/digital-factory-data/patches/provisioning/

The script will be automatically executed towards the end of Jahia startup.

Executing a remote provisioning script

This method allows you to instruct Jahia to fetch its provisioning script from a remote URL, providing slightly more flexibility than the method above (not needing to copy a script file).

docker run -p 8080:8080 -e EXECUTE_PROVISIONING_SCRIPT=http://my-server.com/provisioning.yml jahia/jahia:8.0.3.0 

Running this command is equivalent to providing jahia with the following provisioning script:

- include: "http://my-server.com/provisioning.yml"

Building docker images

For repeatable actions (always installing the same module, always performing the same configuration), a new image can be built to already include such actions, meaning they will not have to be performed, at runtime, for every single start of Jahia.

For example, if you developed your own module and know that this module will always be installed, on all your instances of Jahia, then the module could be packaged directly in your docker image.

Although this approach accelerates startup time, it can add complexity to your DevOps workflow, as a new version of your own image would need to be generated for every Jahia release you're planning to use.

As a result, you're reducing runtime complexity, likely accelerating Jahia startup by adding a build stage, but also increasing maintainability overhead.

Our jahia/jahia-discovery image for example is built on top of our jahia/jahia-ee image, to include additional features in the image without having to install these every time Jahia would start.

Adding system packages

We designed the images to only contain a minimal set of external libraries as it both reduces the size of the image and potentially increases its security (fewer dependencies means fewer chances of being exposed to a security vulnerability). Typically, we will ensure that the images contain all of the dependencies required by Jahia and its supported modules.

But it also means that if your custom module requires an additional library, the only method available to add a system package (such as installing an additional library with apt) is to create your own image using Jahia releases as a base.

You can use the instructions below to perform such a modification.

Create your own image (simple)

Creating your own image is as simple as using one of our jahia images (such as jahia/jahia-ee) as a base image in a Dockerfile and performing any modifications on the container.

The process of creating Dockerfiles is widely documented online, so this part of the documentation will be focused on a simple example, packaging my-module.jar with your Jahia image.

We will begin by creating a folder:

mkdir ~/my-jahia

Copy to this folder your module my-module.jar

In this folder, create a Dockerfile with the following content:

FROM jahia/jahia-ee:8.0.3.0

COPY my-module.jar /usr/local/tomcat/digital-factory-data/modules/

The above Dockerfile is pretty self-explanatory, it begins with jahia 8.0.3.0 enterprise image and copies your module to the modules folder.

The entry point script (and its CMD command) is detailed in Jahia core Dockerfile which will be inherited from the base image. The entrypoint command can easily be expanded and/or chained to customize Jahia startup.

The image can then be built using the following command:

docker build my-image:latest .

This image will then be stored in your local Docker cache and can be started using the following command:

docker run -p 8080:8080 my-image:latest

Create your own image (advanced)

There's a more advanced technique that can be used to build your own image.

Imagine you've been using a provisioning script to extend Jahia's images and keep repeating the execution of this script, over and over. This script can actually be used as part of image creation.

We will begin by creating a folder:

mkdir ~/my-advanced-jahia

Copy to this folder your provisioning script my-provision.yml

In this folder, create a Dockerfile with the following content:

FROM jahia/jahia-ee:8.0.3.0

RUN mkdir -p /usr/local/tomcat/digital-factory-data/patches/provisioning
COPY my-provision.yml /usr/local/tomcat/digital-factory-data/patches/provisioning/

RUN /usr/local/bin/entrypoint-ee.sh & \
        /usr/local/bin/alive.sh localhost 8080 && \
        /usr/local/tomcat/bin/shutdown.sh

The above script will copy your provisioning script in the container filesystem. During. build (and not at runtime), Jahia will start, wait for it to become "alive", it will then install the provisioning script and finally shut down (saving its filesystem content since this is a build). This will result in a modified image including the result of your script execution. 

Run the following command to build your image:

docker build my-image:latest .

When you will start that image, it will already include the modifications detailed in your provisioning script.

Although this provisioning technique is very powerful, always keep in mind your environment when designing your provisioning script. This technique is useful for actions resulting in a modification of your Jahia instance, such as installing modules, copying artifacts, or setting up configurations. This is not applicable for any action modifying a live database, since you're packaging Jahia with this technique, not the database itself.