Extending the Web Server in Liferay PaaS

This article outlines the high-level steps for creating a custom image for the PaaS web server (nginx) service.

The purpose of this post is to extend the image provided by Liferay PaaS to include a custom module — ngx_brotli, a widely-used compression module that improves web performance by reducing response sizes.

While Liferay PaaS offers a robust and opinionated platform for deploying DXP-based solutions, it also introduces constraints that can make low-level customizations like this more complex.

Extending any core image  is not recommended and Liferay does not provide any kind of support for customized service images. Please refer to the Liferay Cloud Support Coverage and Policies on Custom Images and Services for detailed information.

Steps to override the web server (nginx) image

To achieve the proposed goal, we will try to create a custom Docker image based on Liferay's image. Creating an image from scratch is outside the scope.

Useful resources to follow this guide:

Let's get started!

Extend the original NGINX docker image.

You will need to access to your webserver folder and add a new Dockerfile in the following path:
<workspace-folder>/webserver/Dockerfile to override the webserver image.

Dockerfile

from liferaycloud/nginx:1.24.0-6.1.6

COPY configs /docker-init.d/configs

The directive COPY configs /docker-init.d/configs is required to include any custom configurations in the image; otherwise, they will be ignored. However, this step might not be supported in future liferaycloud/nginx releases and should be reviewed accordingly.

Build and setup the custom nginx module

Now we are going to install and enable ngx_brotli which allows Brotli compression support for modern browsers - caniuse.com/brotli.

Since we are extending an already compiled Nginx image from Liferay, we will need to compile the module externally. This involves manually downloading Nginx and building the ngx_brotli module.

The goal is to add the custom module in the Dockerfile (like the default image), so make sure you use a similar environment and the exact same Nginx version to generate the corresponding <_module>.so* files.

After compiling and generating ngx_http_brotli_filter_module.so and ngx_http_brotli_static_module.so, create a new folder named webserver/custom_modules and copy both files there.

Then, modify the Dockerfile to include the new modules

from liferaycloud/nginx:1.24.0-6.1.6

COPY custom_modules/ngx_http_brotli_static_module.so /etc/nginx/modules
COPY custom_modules/ngx_http_brotli_filter_module.so /etc/nginx/modules

COPY configs /docker-init.d/configs

Finally, create configs/<env>/nginx.conf to load and configure the module. The following example is intended for testing purposes only.

worker_processes  2;

load_module modules/ngx_http_headers_more_filter_module.so;
load_module modules/ngx_http_auth_spnego_module.so;
load_module modules/ngx_http_modsecurity_module.so;
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
...
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main escape=${LCP_WEBSERVER_LOG_ESCAPE}  '${LCP_WEBSERVER_LOG_FORMAT}';
    ...
    brotli on;
    brotli_comp_level 6;
    brotli_static on;
    brotli_types application/atom+xml application/javascript application/json application/vnd.api+json application/rss+xml
             application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype
             application/x-font-ttf application/x-javascript application/xhtml+xml application/xml
             font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon
             image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml;
    ...
...

Note: The default nginx.conf can be reviewed by starting a local container:

# Inspect container
docker run -it -u root --entrypoint /bin/bash --name test liferaycloud/nginx:1.24.0-6.1.6
# Cleanup
docker rm test
docker rmi liferaycloud/nginx:1.24.0-6.1.6

Deploy and test

The new webserver service is now ready for testing and deployment in the intended environment.

cd webserver/
lcp deploy --project= --environment=

After successful deployment, inspect the HTML using any modern browser (e.g., Chrome) and verify that the Content-Encoding:br header is present.


End notes

Although I enjoyed working on this simple proof of concept, extending a PaaS base image should not be the default approach:

  1. Avoid overriding by default and first verify if no other options are available. Liferay support can evaluate your request for consideration in future releases or suggest alternative solutions.
  2. The evolution of Liferay PaaS images is unpredictable. This solution will require ongoing maintenance and might not be compatible with future releases.
  3. Customizing or overriding service images may result in loss of support.