How to create your own basic Node Lighthouse audit service inside a Docker container

Berry de Witte
Mar 24 · 3 min read

At Wehkamp we wanted to collect and visualize the performance of our website. Of course there are third-party tools that can offer you this information, but we also wanted to collect the data ourselves and act upon it in realtime if needed. That’s why we thought of a service that could give us the performance data by auditing the website multiple times a day with Google’s Lighthouse.

Setting up Docker
As we are using an Alpine version of Node we need the Alpine Linux package management (apk) to get chromium. With the following lines added to your dockerfile chromium will be installed and ready to use.

RUN apk --no-cache upgrade && apk add --no-cache chromiumENV CHROME_BIN=/usr/bin/chromium-browser

Creating the service
For this service we use the express framework, combined with the needed lighthouse and chrome-launcher packages. As we also wanted to schedule the audits for every 10 minutes, we added the node-cron package.

In the service we added the list of URLs that needs to be audited. Every URL chrome will be started and the lighthouse package will do the audit. After collecting the results, it’s up to you what to do with it.

Beneath you will see the basic version of the service. For more detailed settings or configurable options, see the documentation of the lighthouse and chrome packages.

const express = require("express");
const chromeLauncher = require("chrome-launcher");
const lighthouse = require("lighthouse");
const cron = require("node-cron");
const urls = [
const opts = {
chromeFlags: ["--headless", "--disable-gpu", "--no-sandbox"]
const config = {
extends: "lighthouse:default"
async function launchChromeAndRunLighthouse(url, opts, config) {
try {
const chrome = await chromeLauncher.launch(opts);
if (chrome) {
const results = await lighthouse(
{ port: chrome.port },
await chrome.kill();
return results && results.lhr;
} catch (err) {
await chromeLauncher.killAll();
function processItems(index) {
if (index < urls.length) {
const results = await launchChromeAndRunLighthouse(
// do something with the resultsprocessItems(index + 1);
cron.schedule("*/10 * * * *", function() {
const app = express();
const port = 5000;
app.listen(port, () =>
console.log(`Lighthouse service is listening on ${port}!`)

Visualizing the data
We chose to store our collected data as metrics in Prometheus, from where we can easily visualize it into graphs with Grafana.

First contentful paint graph in Grafana
First contentful paint graph in Grafana

Thank you for taking the time to read this story! If you enjoyed reading this story, clap for me by clicking the 👏🏻 below so other people will see this here on Medium.

I work at one of the biggest e-commerce companies of 🇳🇱
We do have a Tech blog, check it out and subscribe if you want to read more stories like this one. Or look at our job offers if you are looking for a great job!


Berry de Witte

Written by

senior front-end developer @


We'll try to keep up and post on the stuff we're doing and discovering. Interesting in working @wehkamp? Check out

More From Medium

More on JavaScript from wehkamp-techblog

Related reads

Related reads

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade