How to install custom fonts on a nodejs image using fontconfig
I recently had to generate a custom image from a Node.js backend, and I chose to use Sharp to take an SVG and convert it into a PNG, since we were already using Sharp and it seemed like the most feasible thing to do.
However, I found it a bit less unintuitive how to add custom fonts to the rendered image. I found that locally - given I had the required font installed on my OS - it would work just fine. However, in production font's wouldn't load correctly.
So I thought I'd write this step-by-step guide because that's what I was missing when researching this.
libvips and Sharp
So Sharp
is responsible for rendering the PNG based on the SVG, and Sharp uses libvips
which uses librsvg
under the hood which uses fontconfig (yeah, good luck on that documentation).
So the thing to do is:
- Ensure
fontconfig
is installed - Ensure your fonts are valid, in the correct format and present in the environment
Uploading your fonts
What I did was to create a fonts
folder inside my project root (feel free to place this wherever you see fit), and then ensure that this folder is copied to the correct location when building the image.
Another thing to note is that initially I tried with .otf
fonts, however, that didn't seem to work, so I instead converted them to .ttf
using cloudconvert.
Next step is to ensure fontconfig
is installed in your environment.
Installing fontconfig
in your Dockerfile
I use Docker to build my applications, so I changed my Dockerfile
to look something like this:
FROM node:16-bullseye-slim AS production
COPY --chown=node:node --from=build /usr/src/app/node_modules ./node_modules
COPY --chown=node:node --from=build --chmod=755 /usr/src/app/fonts ./usr/local/share/fonts
RUN apt-get update; apt-get install -y fontconfig
RUN fc-cache -f -v
This will:
- Copy the
fonts
folder in your project root to/usr/local/share/fonts
(which is one of the locationsfontconfig
will look for fonts) - Install
fontconfig
and clear any font cache - which might not be needed, but is a cheap thing to do.
You can also exec/ssh into your running instance and install fontconfig using: apt-get update; apt-get install -y fontconfig
.
Afterwards you may run fc-cache -f -v
to find out where exactly fontconfig
tries to look for fonts (thats how I found /usr/local/share/fonts
).
That's it. Afterwards my custom fonts were rendering correctly. My SVG would look something like this:
<text font-family="Cera Pro" font-size="44" font-weight="500">
Debugging
If you're still having issues try these steps:
- Run
fc-list
this will list which fontsfontconfig
have found - You may need a
fonts.conf
file inside yourfonts
folder (I did seemingly not need that)
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<dir>/fonts</dir>
<config></config>
</fontconfig>
- Try to validate your font
- Feel free to comment in the comment section and I shall try to help out