ASP.NET Core

Using wkhtmltopdf with Docker

Recently I needed to get wkhtmltopdf working in a Docker container with ASP.NET Core. The wonderful thing about Docker containers is that all dependencies are packaged up so you don’t have to worry about installs, versions, deployments, etc. But it does mean setting up the initial environment is a little trickier.

TL:DR Gimme the Dockerfile

For the impatient the full Dockerfile is as follows:

FROM microsoft/aspnetcore:1.1.2

COPY lib/wkhtmltox /usrtmp
RUN (cd /usrtmp && tar c .) | (cd /usr && tar xf -) && \
    chmod 555 /usr/bin/wkhtmltopdf && \
    apt-get update && \
    apt-get install -y --no-install-recommends zlib1g fontconfig libfreetype6 libx11-6 libxext6 libxrender1 && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY bin/Release/PublishOutput .
ENTRYPOINT ["dotnet", "Site.dll"]

Version Issues

You need to run a new enough version to operate correctly in headless mode on newer versions of Linux. 0.12.1-2 is the current version used by Debian, and this will not work. I used the latest 0.12.4 from the main site. Older versions also have heavy dependencies on X11, severely bloating your container.

The default package available in apt will not work.

Permissions Issues

By default, copying files into the Docker container will result in them being read-only, no execute permissions. Additionally, you can’t just do a RUN chmod and expect the files to have the updated permissions. This is due to a bug (maybe?) where you can’t really amend the permissions of another layer – it just doesn’t work. Instead you need to copy the files to one place, then apply your chmod changes:

COPY lib/wkhtmltox /usrtmp
RUN (cd /usrtmp && tar c .) | (cd /usr && tar xf -) && \
    chmod 555 /usr/bin/wkhtmltopdf

This copies the binaries from lib/wkhtmltox to the /usrtmp directory in the image, then moves the files to the real location of /usr. Finally, we set execute permissions for the binary itself.

Dependency Issues

Finally, wkhtmltopdf requires certain dependencies to be present to function. These can be installed as usual via apt:

RUN (apt-get update && \
    apt-get install -y --no-install-recommends zlib1g fontconfig libfreetype6 libx11-6 libxext6 libxrender1 && \
    rm -rf /var/lib/apt/lists/*

We have a few extra options here above what you’d normally run on your own personal Linux install:

–no-install-recommends

We only want the libraries we absolutely must have to make the tool work. So, this flag ensures only the minimum is installed, and not any extra utility packages that might be useful in a full-install. Remember this is a container, so the bare minimum is all we’ll ever need.

rm -rf /var/lib/apt/lists/*

Once we’ve got all the packages installed, we won’t be using the package cache again. So, remove it to keep the container size down.

Posted by Dan in Guides, Programming, 1 comment