Click here to Skip to main content
15,867,141 members
Articles / Containers / Docker

Running Puppeteer under Docker

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
14 Jan 2022CPOL2 min read 5.3K   1
How to get Puppeteer working under Docker
In this post, you will learn about how to get Puppeteer to work under Docker.

I recently tried to dockerise an old hobby project and unsurprisingly, a couple of things broke. Some of these were fairly simple fixes so I won’t go into their details - but I will go into a fairly obscure one, which was caused by puppeteer. Regarding the application itself, it does a few things, but for the purposes of this article, let’s just say that it renders some reports using Puppeteer and NodeJS (while running as a .NET app).

Dance Monkey, Dance Monkey, Dance…Wait, What?

Image 1

If you haven’t heard of Puppeteer, it’s basically a NodeJS library that allows you to run (and control) an instance of headless chrome, i.e., - an instance of Google chrome without a UI. In this project, I was using it to render PDF exports of reports. Running natively, it worked like a charm. But under docker, well… I’m writing this article after all, aren’t I?

Hold Up, Let’s See Your Docker Setup First

I thought you might say that! Well, first here’s the dockerfile.

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["MyApplication.API/MyApplication.API.csproj", "MyApplication.API/"]
COPY ["MyApplication.Common/MyApplication.Common.csproj", "MyApplication.Common/"]
COPY ["MyApplication.Data/MyApplication.Data.csproj", "MyApplication.Data/"]
COPY ["MyApplication.Logic/MyApplication.Logic.csproj", "MyApplication.Logic/"]
RUN dotnet restore "MyApplication.API/MyApplication.API.csproj"
COPY . .
WORKDIR "/src/MyApplication.API"
RUN dotnet build "MyApplication.API.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "MyApplication.API.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApplication.API.dll", "--environment", "Docker"]

# Install node and npm
RUN apt-get update
RUN apt-get install nodejs=12.22.5~dfsg-2~11u1 -y
RUN apt-get install npm=7.5.2+ds-2 -y
ENV NODE_ENV=production

# Install node modules for reports
WORKDIR "/app/Reports/jsreport"
RUN npm install

# Set the directory back so dotnet is able to run the application
WORKDIR "/app"

Basically, I load the ASP.NET 6 base image, build the solution, publish it, install require node modules and set the dotnet program as the entry point of the container.

Then I build an image using docker build -t myimage -f ./MyApplication.API/Dockerfile .

Note that in order for the build step in the docker file to work, the image has to be created at the solution level and not the project level - since all of the projects need to be built. Hence why I’m using the solution directory when we build the image.

Then I run a container using docker run -p 127.0.0.1:80:80/tcp myimage.

So far so good! But after invoking one of the reports yields an internal server error.

Show Me the Errors!

Image 2

Well, since this is running under docker (and this is just a hobby app, I’m using old-school rolling file logs), I actually need to sh into the container first to see the logs. So first to get the id of the container: docker ps, and once we have the id of the container: docker exec -it CONTAINER_ID /bin/bash. Opening the error log reveals:

  Jering.Javascript.NodeJS.InvocationException: Failed to launch chrome!
/app/Reports/jsreport/node_modules/puppeteer/.local-chromium/linux-609904/chrome-linux/chrome: 
error while loading shared libraries: libnss3.so: cannot open shared object file: 
No such file or directory

TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md

Error: Failed to launch chrome!

Interesting! Following the link provided and scrolling down to Running Puppeteer under Docker tells you that we basically need to add a step in our dockerfile to install the necessary libraries (particularly libnss3.so) in order for headless chrome to run. The dockerfile in their example is a bit verbose with some unnecessary steps, but the real magic is basically just:

# Install latest chrome dev package and fonts to support major charsets 
# (Chinese, Japanese, Arabic, Hebrew, Thai and a few others)
# Note: this installs the necessary libs to make the bundled version of Chromium that Puppeteer
# installs, work.
RUN apt-get update \
    && apt-get install -y wget gnupg \
    && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> 
              /etc/apt/sources.list.d/google.list' \
    && apt-get update \
    && apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei 
                       fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \
      --no-install-recommends \
    && rm -rf /var/lib/apt/lists/*

And voila! Puppeteer is now working under Docker. Hope this helped someone out, or was at least an interesting read. :)

Catch ya!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Australia Australia
G'day guys! My name is Jason, and I'm a backend software engineer living in Sydney, Australia. I enjoy blogging, playing chess and travelling.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Ștefan-Mihai MOGA14-Jan-22 20:47
professionalȘtefan-Mihai MOGA14-Jan-22 20:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.