How to install custom dependencies on Azure Functions on Linux

I recently encountered an issue with Azure Functions on Linux, which is in preview right now (https://blogs.msdn.microsoft.com/appserviceteam/2017/11/15/functions-on-linux-preview/) while trying to use an open-source library that had some additional dependencies to be able to run successfully, namely wkhtmltopdf - https://github.com/wkhtmltopdf/wkhtmltopdf.

While trying to set up a basic function that was using this library, I got the following error:

./wkhtmltopdf: error while loading shared libraries: libXrender.so.1: cannot open shared object file: No such file or directory

Doing a search on the project's GitHub page, I found this issue: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/1515

and I figured that there's a number of packages that the Linux image needs to have in order for this library to work correctly.

Because Azure Functions on Linux is built on containers, you can host your functions in your own custom container, as described here: /en-us/azure/azure-functions/functions-create-function-linux-custom-image

Usually, Function Apps on Linux are based on this image here: https://github.com/Azure-Samples/functions-linux-custom-image/blob/master/Dockerfile

At the bottom of the Dockerfile, you can add a command that installs the packages you need for your function to work, for example:

 RUN apt-get update \
&& apt-get install -y --no-install-recommends openssl build-essential libssl-dev libxrender-dev git-core libx11-dev libxext-dev libfontconfig1-dev libfreetype6-dev fontconfig

After you have the Dockerfile ready, in the folder that contains the Dockerfile, paste the host.json file and the folder containing your function, as shown below:

and then build the image, by following the steps in the how-to article on Microsoft Docs mentioned above.

After building the image and publishing it to a Docker Hub, you should create a new function app by using Azure CLI and giving the custom container as a parameter.

First, you should create a new Linux App Service plan:

 az appservice plan create --name 'plan_name' --resource-group 'resource_group_name' --sku S1 --is-linux

and then create the Function App, based on the custom image you published, by running the following command:

 az functionapp create --name 'app_name' --storage-account  'storage_name'  --resource-group 'resource_group_name' \
--plan 'plan_name' --deployment-container-image-name 'docker-id/docker-image-name:docker-image-tag'

where

 'docker-id'

is the name of your Docker Hub account.

After this, the portal will look like the one below:

The functions will be Read Only, so you will not be able to edit them or create new ones directly from the portal, you would have to do that from your filesystem and create new container images and publish them.

As you can see, the function is working and I got a 200 OK response and a PDF output, as shown in the image above.

Have fun with custom containers!