One solution is to include the libraries required by PhantomJS in your Lambda function .zip file. I'll break this down into several steps.
Determine which libraries to include
Your error message states that a shared library is missing. Let's find exactly what PhantomJS is looking for by installing it in a Docker container and checking its runtime dependencies. The nodejs10.x AWS Lambda Runtime uses Amazon Linux 2, but the steps are similar for earlier runtimes.
On your host system, run an Amazon Linux 2 Docker container:
$ docker run -it --rm amazonlinux:2.0.20190508
In the container, install PhantomJS and inspect its dependencies:
bash-4.2$ yum install -y bzip2 tar
bash-4.2$ curl -LO https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
bash-4.2$ tar xf phantomjs-2.1.1-linux-x86_64.tar.bz2
bash-4.2# ldd ./phantomjs-2.1.1-linux-x86_64/bin/phantomjs
linux-vdso.so.1 (0x00007ffdd251f000)
libz.so.1 => /lib64/libz.so.1 (0x00007f35d0439000)
libfontconfig.so.1 => not found
libfreetype.so.6 => not found
...
We see that libfontconfig and libfreetype are missing.
Install the libraries
Next, we'll download and extract the required libraries, then copy them to the host system. Note that libfontconfig depends on libexpat, so we'll install that as well.
In the container:
bash-4.2$ yum install -y yum-utils rpmdevtools
bash-4.2$ cd /tmp
bash-4.2$ yumdownloader fontconfig.x86_64 freetype.x86_64 expat.x86_64
bash-4.2$ rpmdev-extract *.rpm
Copy the libraries into a directory:
bash-4.2$ mkdir -p /deps
bash-4.2$ cp /tmp/*/usr/lib64/* /deps
Also copy the fontconfig configuration file:
bash-4.2$ cp /tmp/*/etc/fonts/fonts.conf /deps
Next, on the host, get the Docker container ID and copy the files from the container to the host. Below, lambda-node-phantom
is the directory where you cloned the https://github.com/TylerPachal/lambda-node-phantom repository:
$ cd lambda-node-phantom
$ docker ps
$ docker cp <CONTAINER_ID>:/deps/ .
$ mv deps/* . && rmdir deps
Update the Lambda
Update the PhantomJS binary in your directory to the version downloaded in the Docker container above. Make sure that index.js
refers to the correct name for the latest version; in version 2.1.1 it's named phantomjs
.
Next, add the following line to index.js
so that fontconfig finds fonts.conf
in the Lambda root directory:
process.env['FONTCONFIG_PATH'] = process.env['LAMBDA_TASK_ROOT'];
Finally, re-create the Lambda function .zip file, including the native libraries and font.conf
:
$ zip -y /path/to/lambda-node-phantom-dist.zip .
The -y
option stores symbolic links as links instead of the referenced file. To save space, make sure that the .git
directory is not included in the .zip file.
Test the Lambda
In the AWS Lambda console, upload the new Lambda function .zip file and test the Lambda function. PhantomJS should now run without errors, and your function should return "hello from phantom!" If not, check the stderr
returned by the PhantomJS child process for information.
It's likely that you'll need to modify fonts.conf
and/or include additional files for fonts to be rendered properly.