AdoptOpenJDK/openjdk-docker

Alpine images missing fontconfig

gdams opened this issue · 23 comments

gdams commented

Alpine images need the following command added:

RUN apk add --no-cache fontconfig
RUN ln -s /usr/lib/libfontconfig.so.1 /usr/lib/libfontconfig.so && \
    ln -s /lib/libuuid.so.1 /usr/lib/libuuid.so.1 && \
    ln -s /lib/libc.musl-x86_64.so.1 /usr/lib/libc.musl-x86_64.so.1
ENV LD_LIBRARY_PATH /usr/lib

As discussed in #75

@gdams I've not seen the need to symlink libraries in the past on Alpine to get the font support working. Considering how old the linked issue is, ...

We've left that workaround in our images ever since we encountered that issue. I'll test it over the next few weeks and see if it's still necessary with the newest Docker images.

We've left that workaround in our images ever since we encountered that issue. I'll test it over the next few weeks and see if it's still necessary with the newest Docker images.

@ReillyTevera any luck?

@karianna I am not OP, but I am also facing issues that were resolved with a workaround mentioned here #75 (comment)

demo-gh529.zip

I have attached a testframe based on spring-boot (1:1 off of https://start.spring.io/), where I added some code that tries to load an Arial.tff which I have copied from my W10 machine. I assume that it is OPs issue as well.

Strangely enough, we dont face this issue with a build from abot 2020-10-* (but I need to refine that from my side, I have no luck reproducing it when pulling the same tag)

It is self-contained and only requires this call for testing:

docker build . -t alpinefontconfig && docker run alpinefontconfig -it

Where this Dockerfile will produce a running application:

FROM adoptopenjdk/openjdk15:alpine as builder
WORKDIR /workspace/app

COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src

RUN chmod +x mvnw && ./mvnw install -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)

FROM adoptopenjdk/openjdk11:x86_64-alpine-jre-11.0.10_9

# this comment also adds symlinks + ENV instruction, but this also seems to do the trick
# https://github.com/AdoptOpenJDK/openjdk-docker/issues/75#issuecomment-638496817
RUN apk add --no-cache fontconfig ttf-dejavu

VOLUME /tmp
ARG DEPENDENCY=/workspace/app/target/dependency
RUN mkdir /app
COPY --from=builder ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=builder ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=builder ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","com.example.demo.DemoApplication"]

Output:

C:\Users\ddrop\Downloads\demo-gh529\demo
λ docker build . -t alpinefontconfig && docker run alpinefontconfig -it
...
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.4)

2021-03-31 16:47:17.466  INFO 1 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication using Java 11.0.10 on 6a5c07b0b8e5 with PID 1 (/app started by root in /)
2021-03-31 16:47:17.468  INFO 1 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2021-03-31 16:47:17.939  INFO 1 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 0.752 seconds (JVM running for 0.993)

Whereas commenting out

# RUN apk add --no-cache fontconfig ttf-dejavu

Leads to

λ docker build . -t alpinefontconfig && docker run alpinefontconfig -it
...
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.4)

2021-03-31 16:51:04.375  INFO 1 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication using Java 11.0.10 on 52fa05aed023 with PID 1 (/app started by root in /)
2021-03-31 16:51:04.377  INFO 1 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2021-03-31 16:51:04.677  WARN 1 --- [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fontManager': Invocation of init method failed; nested exception is java.io.IOException: Problem reading font data.
2021-03-31 16:51:04.683  INFO 1 --- [           main] ConditionEvaluationReportLoggingListener :

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-03-31 16:51:04.707 ERROR 1 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fontManager': Invocation of init method failed; nested exception is java.io.IOException: Problem reading font data.
        at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:160) ~[spring-beans-5.3.5.jar:5.3.5]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:422) ~[spring-beans-5.3.5.jar:5.3.5]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1778) ~[spring-beans-5.3.5.jar:5.3.5]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602) ~[spring-beans-5.3.5.jar:5.3.5]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.5.jar:5.3.5]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.5.jar:5.3.5]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.5.jar:5.3.5]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.5.jar:5.3.5]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.5.jar:5.3.5]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.5.jar:5.3.5]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.5.jar:5.3.5]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.5.jar:5.3.5]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:769) ~[spring-boot-2.4.4.jar:2.4.4]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:761) ~[spring-boot-2.4.4.jar:2.4.4]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[spring-boot-2.4.4.jar:2.4.4]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[spring-boot-2.4.4.jar:2.4.4]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1313) ~[spring-boot-2.4.4.jar:2.4.4]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[spring-boot-2.4.4.jar:2.4.4]
        at com.example.demo.DemoApplication.main(DemoApplication.java:10) ~[app/:na]
Caused by: java.io.IOException: Problem reading font data.
        at java.desktop/java.awt.Font.createFont0(Unknown Source) ~[na:na]
        at java.desktop/java.awt.Font.createFont(Unknown Source) ~[na:na]
        at com.example.demo.FontManager.postConstruct(FontManager.java:23) ~[app/:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
        at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389) ~[spring-beans-5.3.5.jar:5.3.5]
        at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) ~[spring-beans-5.3.5.jar:5.3.5]
        at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) ~[spring-beans-5.3.5.jar:5.3.5]
        ... 18 common frames omitted

Strangely enough, we dont face this issue with a build from abot 2020-10-* (but I need to refine that from my side, I have no luck reproducing it when pulling the same tag)

I was now able to reproduce this as well, here is another testframe

demo-gh529-fontConfigProperties.zip

When copying fontconfig.properties to /opt/java/openjdk/lib/ .

version=1
sequence.allfonts=alphabetic/default,dingbats,symbol

The issue does NOT appear without fontconfig (so vanilla image without apk add...) for these two tags:

FROM adoptopenjdk/openjdk11:x86_64-alpine-jre-11.0.9_11
FROM adoptopenjdk/openjdk11-openj9:x86_64-alpine-jre-11.0.9_11_openj9-0.23.0

While it breaks with these (and newer images as well)

FROM adoptopenjdk/openjdk11:x86_64-alpine-jre-11.0.10_9
FROM adoptopenjdk/openjdk11-openj9:x86_64-alpine-jre-11.0.10_9_openj9-0.24.0

Also interesting: with that font-config file, ttf-dejavu is also not necessary anymore, and only following is needed (at least for that test with spring-boot)

RUN apk add --no-cache fontconfig

Please all forget past experiences. A lot has changed since then, most recently in January. Everything from before then is moot.

We unbundled Freetype with the January 2021 updates. Since then, you have to bring your own copy. See https://blog.adoptopenjdk.net/2021/01/adoptopenjdk-8u282-11010-and-1502-available/ for the announcement. https://blog.adoptopenjdk.net/2021/01/prerequisites-for-font-support-in-adoptopenjdk/ lists what's necessary except for Alpine. But you can see the equivalent in https://github.com/AdoptOpenJDK/openjdk-infrastructure/blob/6265fbf2648bd495b1dff903af371897ca7f12e9/ansible/playbooks/AdoptOpenJDK_Unix_Playbook/roles/DockerStatic/Dockerfiles/Dockerfile.alp311#L4-L5.

One thing you have to pay attention to: If the JDK was built with glibc, you may not pull in the Alpine packages that are based on musl libc. Otherwise, you end up with the mess I described in #520 (comment).

Ah okay, understood (I think).

Instead of being halfbaked (where some libs would still be missing), images are now blank regarding tools that would be needed for font processing?

One thing you have to pay attention to: If the JDK was built with glibc, you may not pull in the Alpine packages that are based on musl libc

IIRC, that musl/glibc incompatibility may occur for anything before jdk16? https://openjdk.java.net/jeps/386 , jdk16 builds and onward are based on musl. And this is not backported to e.g. 8/11, correct?

From my understanding, alpine images then need following libs that should be installed by the user, not provided generally?

RUN apk add --no-cache fontconfig ttf-dejavu

That seems to be the minimum, based on that article I used FontTest as following:

FontTest.java:

import java.awt.*;

public class FontTest {

    public static void main(String[] args) {
        String[] names = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();

        System.out.println("Found " + names.length + " fonts:");

        for (String name : names) {
            System.out.println(name);
        }
    }
}

DockerFile:

FROM adoptopenjdk/openjdk11:alpine as builder
WORKDIR /workspace/app

COPY FontTest.java .

RUN javac FontTest.java

FROM adoptopenjdk/openjdk11:jre-11.0.10_9-alpine
RUN apk add --no-cache fontconfig ttf-dejavu

COPY --from=builder /workspace/app/FontTest.class .

ENTRYPOINT ["java","FontTest"]

Output:

λ docker build . -t alpinefontconfig && docker run alpinefontconfig -it
...
Found 18 fonts:
DejaVu LGC Sans
DejaVu LGC Sans Condensed
DejaVu LGC Sans Light
DejaVu LGC Sans Mono
DejaVu LGC Serif
DejaVu LGC Serif Condensed
DejaVu Math TeX Gyre
DejaVu Sans
DejaVu Sans Condensed
DejaVu Sans Light
DejaVu Sans Mono
DejaVu Serif
DejaVu Serif Condensed
Dialog
DialogInput
Monospaced
SansSerif
Serif

Instead of being halfbaked (where some libs would still be missing), images are now blank regarding tools that would be needed for font processing?

From my POV, container images should bring everything needed to run a Java application. This includes freetype, fontconfig, and a couple of fonts. Any image should install libxrender, libxi, libxtst, alsa-lib, libx11, fontconfig, libxext, freetype, zlib, ttf-dejavu.

IIRC, that musl/glibc incompatibility may occur for anything before jdk16?

At the moment, yes.

jdk16 builds and onward are based on musl.

We have tarballs for musl. Ready-made container images are still based on glibc, for some reason.

And this is not backported to e.g. 8/11, correct?

8 is unlikely, 11 might be possible, but I'm not aware of any effort to backport JEP 386 to 11.

From my POV, container images should bring everything needed to run a Java application... Any image should install ...

Would that also include ready-made images? So future builds would have these libs installed?

Would that also include ready-made images? So future builds would have these libs installed?

They should, but I'm only the support guy.

Ah, gotcha.

Chiming back in, as far as I can tell the linking workaround is no longer necessary with current JDK Alpine images. We were able to remove the symlink commands (while retaining the commands to install fontconfig and ttf-dejavu) and were not able to reproduce our original issue. I note though that our issue (coming from #75) was never that the fontconfig package was missing but that it required manual linking once installed to get it working with Adoptopenjdk. This issue now seems to be resolved (I assume it was due to musl/glibc incompatibilities).

I also believe that the base Adoptopenjdk images should be kept as slim as possible with only the required libraries to run the JDK/JVM. If a majority of users do not need font handling then the fontconfig library should be kept out of the adoptopenjdk image and should be installed by any downstream consumer of that image if needed.

Side note, @aahlenst are you sure that the JDK images are not linked against musl already? I used ldd against a few of the binaries and a few libraries and didn't notice any glib links, just musl ones.

with only the required libraries to run the JDK/JVM

But what is defined as "required libraries"?. java.awt.* requires some of these libraries and is also part of the jdks public API. On the other hand, images should be kept to a minumum, especially for alpine images IMO.

My team is mostly interested in whether or not this is a bug or an intended state. My takeaway so far is that it is intended. Mostly based on the reasoning here: https://blog.adoptopenjdk.net/2021/01/prerequisites-for-font-support-in-adoptopenjdk/

Azul appears to handle it similarily (https://support.azul.com/hc/en-us/articles/360034030692-Using-Fonts-with-OpenJDK-Zulu) while for Corretto also has some open tickets (corretto/corretto-11#118, corretto/corretto-11#124)

@DRoppelt I would define "required libraries" as "all that the JVM itself requires to be fully functional AND anything required for a basic 'hello world' program to be compiled and ran". Anything beyond that, even if part of the JDKs public API, should be omitted from the image in the interest of keeping it as small as possible. If think it would then be useful if there was a documentation page where "missing" JDK functionality is listed along with the native library that enables it.

FYI, this is not needed anymore with JDK16 🎉

FYI, this is not needed anymore with JDK16 🎉

Hm does not look like it to me. Which tag is working for you? Latest JRE&JDK build did not work

docker build . -t alpinefontconfig && docker run alpinefontconfig -it
[+] Building 12.5s (12/12) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                                            0.0s
 => => transferring dockerfile: 345B                                                                                                                                            0.0s
 => [internal] load .dockerignore                                                                                                                                               0.0s
 => => transferring context: 2B                                                                                                                                                 0.0s
 => [internal] load metadata for docker.io/adoptopenjdk/openjdk16:alpine-jre-nightly                                                                                            1.1s
 => [internal] load metadata for docker.io/adoptopenjdk/openjdk16:alpine                                                                                                        0.6s
 => [builder 1/4] FROM docker.io/adoptopenjdk/openjdk16:alpine@sha256:c08550f50236a8ef52380e8439b608c46d8750c76ba2a91e350fc64bd623c5cb                                          0.0s
 => [stage-1 1/2] FROM docker.io/adoptopenjdk/openjdk16:alpine-jre-nightly@sha256:477ec5cd29af5238f4ab95df57771d2a299fec815d9dada2c84a3060aaf66747                             11.2s
 => => resolve docker.io/adoptopenjdk/openjdk16:alpine-jre-nightly@sha256:477ec5cd29af5238f4ab95df57771d2a299fec815d9dada2c84a3060aaf66747                                      0.0s
 => => sha256:477ec5cd29af5238f4ab95df57771d2a299fec815d9dada2c84a3060aaf66747 433B / 433B                                                                                      0.0s
 => => sha256:aa545fb0be4c96ac48e1f12be15cc13530ea281e80e6d20adee1b5958d74ba34 950B / 950B                                                                                      0.0s
 => => sha256:3040a81f9b9b056b1b1dbf39fd03ca0cb6a36ea350330080e39e771d25aa7fe2 3.55kB / 3.55kB                                                                                  0.0s
 => => sha256:fe38772aad47171a5825715a2841c1d0641a7bea38309e4f8276e4672ecb1fc6 406.37kB / 406.37kB                                                                              0.2s
 => => sha256:c84f42e0533e6ed110809081e81128249f62b64489a2105a39bf986f8853eff9 49.71MB / 49.71MB                                                                                8.9s
 => => extracting sha256:fe38772aad47171a5825715a2841c1d0641a7bea38309e4f8276e4672ecb1fc6                                                                                       0.3s
 => => extracting sha256:c84f42e0533e6ed110809081e81128249f62b64489a2105a39bf986f8853eff9                                                                                       2.1s
 => [internal] load build context                                                                                                                                               0.0s
 => => transferring context: 35B                                                                                                                                                0.0s
 => CACHED [builder 2/4] WORKDIR /workspace/app                                                                                                                                 0.0s
 => CACHED [builder 3/4] COPY FontTest.java .                                                                                                                                   0.0s
 => CACHED [builder 4/4] RUN javac FontTest.java                                                                                                                                0.0s
 => [stage-1 2/2] COPY --from=builder /workspace/app/FontTest.class .                                                                                                           0.0s
 => exporting to image                                                                                                                                                          0.0s
 => => exporting layers                                                                                                                                                         0.0s
 => => writing image sha256:af9d14b55aa081f9c33988ef7f95acbc8d6ac03fc90e582db44087d821cc9620                                                                                    0.0s
 => => naming to docker.io/library/alpinefontconfig                                                                                                                             0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Exception in thread "main" java.lang.UnsatisfiedLinkError: /opt/java/openjdk/lib/libfontmanager.so: Error loading shared library libfreetype.so.6: No such file or directory (needed
by /opt/java/openjdk/lib/libfontmanager.so)
        at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)
        at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(Unknown Source)
        at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(Unknown Source)
        at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(Unknown Source)
        at java.base/jdk.internal.loader.NativeLibraries.findFromPaths(Unknown Source)
        at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(Unknown Source)
        at java.base/java.lang.ClassLoader.loadLibrary(Unknown Source)
        at java.base/java.lang.Runtime.loadLibrary0(Unknown Source)
        at java.base/java.lang.System.loadLibrary(Unknown Source)
        at java.desktop/sun.font.FontManagerNativeLibrary$1.run(Unknown Source)
        at java.base/java.security.AccessController.doPrivileged(Unknown Source)
        at java.desktop/sun.font.FontManagerNativeLibrary.<clinit>(Unknown Source)
        at java.desktop/sun.font.SunFontManager$1.run(Unknown Source)
        at java.desktop/sun.font.SunFontManager$1.run(Unknown Source)
        at java.base/java.security.AccessController.doPrivileged(Unknown Source)
        at java.desktop/sun.font.SunFontManager.<clinit>(Unknown Source)
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Unknown Source)
        at java.desktop/sun.font.FontManagerFactory$1.run(Unknown Source)
        at java.base/java.security.AccessController.doPrivileged(Unknown Source)
        at java.desktop/sun.font.FontManagerFactory.getInstance(Unknown Source)
        at java.desktop/sun.java2d.SunGraphicsEnvironment.getFontManagerForSGE(Unknown Source)
        at java.desktop/sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(Unknown Source)
        at java.desktop/sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(Unknown Source)
        at java.desktop/sun.java2d.HeadlessGraphicsEnvironment.getAvailableFontFamilyNames(Unknown Source)
        at FontTest.main(FontTest.java:6)
FROM adoptopenjdk/openjdk16:alpine as builder
WORKDIR /workspace/app

COPY FontTest.java .

RUN javac FontTest.java

FROM adoptopenjdk/openjdk16:alpine-jre-nightly
#RUN apk add --no-cache fontconfig ttf-dejavu

COPY --from=builder /workspace/app/FontTest.class .

ENTRYPOINT ["java","FontTest"]
import java.awt.*;

public class FontTest {

    public static void main(String[] args) {
        String[] names = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();

        System.out.println("Found " + names.length + " fonts:");

        for (String name : names) {
            System.out.println(name);
        }
    }
}

Sorry, what I meant was that I no longer need the hack with symlinks to get rid of errors when installing fonts. I don't see you installing any fonts in your Dockerfile.

your main class + this Dockerfile

FROM adoptopenjdk/openjdk16:x86_64-alpine-jdk-16.0.1_9

RUN apk add --no-cache fontconfig ttf-dejavu

WORKDIR /workspace/app

COPY src/main/java/FontTest.java .
RUN javac FontTest.java

ENTRYPOINT ["java","FontTest"]

gives me:

$ docker build --no-cache -t alpine-fonts-test:latest . ; docker run --rm alpine-fonts-test:latest 
Sending build context to Docker daemon  44.54kB
Step 1/6 : FROM adoptopenjdk/openjdk16:x86_64-alpine-jdk-16.0.1_9
 ---> 025882763767
Step 2/6 : RUN apk add --no-cache fontconfig ttf-dejavu
 ---> Running in 9b63e82cbbaf
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz
(1/11) Installing expat (2.2.9-r1)
(2/11) Installing brotli-libs (1.0.9-r1)
(3/11) Installing libbz2 (1.0.8-r1)
(4/11) Installing libpng (1.6.37-r1)
(5/11) Installing freetype (2.10.4-r0)
(6/11) Installing libuuid (2.35.2-r0)
(7/11) Installing fontconfig (2.13.1-r2)
(8/11) Installing encodings (1.0.5-r0)
(9/11) Installing libfontenc (1.1.4-r0)
(10/11) Installing mkfontscale (1.2.1-r1)
(11/11) Installing ttf-dejavu (2.37-r1)
Executing busybox-1.31.1-r20.trigger
Executing fontconfig-2.13.1-r2.trigger
Executing mkfontscale-1.2.1-r1.trigger
OK: 31 MiB in 28 packages
Removing intermediate container 9b63e82cbbaf
 ---> 438647410fa4
Step 3/6 : WORKDIR /workspace/app
 ---> Running in 40cbe6ccb360
Removing intermediate container 40cbe6ccb360
 ---> e5cfbc617d24
Step 4/6 : COPY src/main/java/FontTest.java .
 ---> bba3d41e29e6
Step 5/6 : RUN javac FontTest.java
 ---> Running in 6563cc172c6f
Removing intermediate container 6563cc172c6f
 ---> 6f9ea6665a06
Step 6/6 : ENTRYPOINT ["java","FontTest"]
 ---> Running in cebfcec7fc60
Removing intermediate container cebfcec7fc60
 ---> 5116cee7733c
Successfully built 5116cee7733c
Successfully tagged alpine-fonts-test:latest
Found 18 fonts:
DejaVu LGC Sans
DejaVu LGC Sans Condensed
DejaVu LGC Sans Light
DejaVu LGC Sans Mono
DejaVu LGC Serif
DejaVu LGC Serif Condensed
DejaVu Math TeX Gyre
DejaVu Sans
DejaVu Sans Condensed
DejaVu Sans Light
DejaVu Sans Mono
DejaVu Serif
DejaVu Serif Condensed
Dialog
DialogInput
Monospaced
SansSerif
Serif

previously, the installation of the fonts was outputting errors, not "it works" without the symlink hack

... it is still missing the packages, but IMHO that's not bad, important is that simply installing them is enough :)

what I meant was that I no longer need the hack with symlinks to get rid of errors when installing fonts. I don't see you installing any fonts in your Dockerfile

I assumed you meant that JDK16 works without anything, so I uncomented the "apk ..." line.

Installation without additional symlinks works for all builds since January'21 or so

Thanks for the conversation folks I think we can close this now

Hi,

even though this is somewhat off-topic, my remarks may be helpful for those who get here searching for this error.

in my case, I encountered the problem in a docker image based on eclipse-temurin:17-jdk-alpine running a webapp that generates excel files using apache poi. after adding the packages fontconfig and ttf-dejavu, not only the class FontText.java given above ran successfully, but also it was possible to generate excel files, which before resulted in this exception:

...
Caused by: java.lang.UnsatisfiedLinkError: /opt/java/openjdk/lib/libfontmanager.so: Error loading shared library libfreetype.so.6: No such file or directory (needed by /opt/java/openjdk/lib/libfontmanager.so)
    at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)

so the same problem is still there in temurin 17 but fortunately it can be solved using the same fix.

gdams commented

Thanks for your comments here @Remigius2011 I'll raise a PR at https://github.com/adoptium/containers to get this fixed