Back to home

XM Cloud Lighthouse Vercel Integration – Part – 1 – Running Lighthouse in Docker Windows Container with Puppeteer

What is this about ?

Leveraging XM Cloud API’s and Webhooks to powerup integrations‘ – this was the topic we presented @SUGCON 2023, Malaga Spain focusing on how the XM Cloud APIs and Webhooks can be used to build integrations effectively for the Composable solutions out of the box.

We did a demo as part of the presentation with an XM Cloud – Vercel Integration application to run lighthouse audits for the XM Cloud front end rendering host application enabling a quality check before a build gets promoted to any environment and so on.

This blog is a small portion of it that explains how we can run lighthouse in a containerised windows environment.

A Quick note on lighthouse

Ligththouse as we all aware, it is commonly used tool to measure the quality of the web pages in terms of SEO, Performance, Best Practices etc., For any given page, it runs series of audits and finally generates the report. It has a dependency over Chrôme. And there are different ways we can run the lighthouse to audit a page like via Cli, Node module etc.,

In our case for the integration application we need to use a headless version of chromium to audit the web pages to measure these factors of a page.

How to get this running in Docker windows containers ?

As mentioned above, Lighthouse depends on Chromium i.e., we need to have one instance of chromium running for lighthouse to work properly. For this, we are going to use the Puppeteer – a node js library that offers various APIs to run Chrome and by default it runs in headless mode.

So we are going to use this node library. Puppeteer offers an docker image but for the linux containers. So let us see how to dockerize the same for windows containers.

It wasn’t straightforward though and let us see below the different challenges in it.

npm i puppeteer – The initial mystery with docker

When you install the puppeteer with npm, it by defaults downloads and installs a recent version of the Chromium as per the notes which is a must for puppeteer to work properly.

I added this package into the solution, up my containers and tried to launch the lighthouse. But it did not go well. The below was the exception I started getting instantly.

As per the docs, the puppeteer should have been installed a recent version of chrome in the location .cache/puppeteer. As it is a docker, the location is below as highlighted.

As you can notice that it did not install any version of chrome and hence the exception was.

Inside my docker file, I am using npm install. So it should basically installed all the packages whichever is configured in the package.json and just to be sure, there is a puppeteer entry with expected version as below.

what could be wrong ? Then just to check as part of the debugging, in my docker file, I installed the puppeteer directly after the npm install like below.

With the above change, if I inspect the container, I was able to notice that there is a version of chrome installed in the required location.

Then I again tried to launch lighthouse. Now the lighthouse gets started as expected and you can also notice the browser path is correct.

However it was not fully working. Now the lighthouse gets started, but it is not able to connect to Chrome instance internally to trigger the audit for the given url. And this is another issue this time !!!

Little progress !!! But yet not fully. Let us see how I resolved this after days of debugging and trying different ways 😦

How this was resolved ?

After a lot of different approches, I was able to find that the Puppeteer installs just a version of chrome. But it did not install the required dependent file for chrome itself to work properly. The files are font files !!!

Yes. For Chrome instance to work properly, it needs some Font files to be installed. As this os a fresh docker container, there are no font files by default and hence the chrome was not able to start.

To resolve this, I needed to install some font files inside my docker container with the below set of docker commands.

After this change, the lighthouse gets started without any issues and I was able to audit the pages as expected.

Dockerizing the instances

nodejs – the base image:-

We need a base nodejs image and the corresponding DockerFile is as below.

# escape=`
ARG PARENT_IMAGE
FROM $PARENT_IMAGE
USER ContainerAdministrator
ARG NODEJS_VERSION
WORKDIR c:\build
RUN curl.exe -sS -L -o node.zip https://nodejs.org/dist/v%NODEJS_VERSION%/node-v%NODEJS_VERSION%-win-x64.zip"
RUN tar.exe -xf node.zip -C C:\
RUN move C:\node-v%NODEJS_VERSION%-win-x64 c:\node
RUN del node.zip
RUN SETX /M PATH "%PATH%;C:\node"
USER ContainerUser

vercel-lighthouse service:-

This is the service that runs the lighthouse with the puppeteer library.

# escape=`
ARG BASE_IMAGE
FROM ${BASE_IMAGE} as base
## Running in Admin context to install the font files
USER ContainerAdministrator
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
## Copy the Font tar file - This is needed for Chrome to run properly
ADD \docker\data\installers\Chrome_Dependent_Fonts.tar /Fonts/
WORKDIR /Fonts/
RUN .\\Add-Font.ps1 Fonts/
## Remove the font files
WORKDIR /
RUN Remove-Item Fonts -Recurse
WORKDIR /app
## Included these lines to avoid garbage collection errors during npm install
ENV GENERATE_SOURCEMAP false
ENV NODE_OPTIONS=--max-old-space-size=8192
EXPOSE 3000
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
## App Installation
WORKDIR /app
COPY . /app
RUN npm ci --ignore-scripts --loglevel warn
RUN npm install
RUN npm install -g puppeteer
RUN npm run build
EXPOSE 3000
## will start app   
ENTRYPOINT "npm run dev"

The docker-compose file would be the below one,

services:
  nodejs:
    image: ${REGISTRY}vercel-lighthouse-nodejs:${VERSION:-latest}
    build:
      context: ./docker/build/nodejs
      args:
        PARENT_IMAGE: ${NODEJS_PARENT_IMAGE}
        NODEJS_VERSION: ${NODEJS_VERSION}
    scale: 0
  vercel-lighthouse:
    image: ${REGISTRY}vercel-lighthouse-integration:${VERSION:-latest}
    build:
      context: .
      dockerfile: docker/build/lighthouse-vercel/Dockerfile
      args:
        BASE_IMAGE: ${REGISTRY}vercel-lighthouse-nodejs:${VERSION:-latest}
    volumes:
    - .:C:\app
    ports:
    - "3000:3000"

The following env file is needed as well,

REGISTRY=sugcon2023.azurecr.io/
VERSION=local
BUILD_CONFIGURATION=debug
NODEJS_PARENT_IMAGE=mcr.microsoft.com/windows/servercore:ltsc2019
NODEJS_VERSION=18.12.1

With this changes above, when you build and up the containers, you should be having the instances up and running without any issues.

As mentioned above, you would need some base font files. The full docker file can be downloaded from this repo. You can clone this repo and try to up to try it out.

Stay tunes for next continuation of this !!!