asciidoctor/docker-asciidoctor

Cannot build PDFs: notoserif-regular-subset.ttf not found in GEM_FONTS_DIR (v1.8.0 and later)

p- opened this issue ยท 19 comments

p- commented

Hello
Thanks for creating the docker-asciidoctor image!

Since Version 1.8.0 and later, we cannot build PDFs anymore because of this error:

No such file or directory - notoserif-regular-subset.ttf not found in GEM_FONTS_DIR

Do you have an idea what could be the cause?

Hello @p- , thanks for reporting!

Could you provide a reproduction case please?

The reason I'm asking is because the test harness has a PDF generation step that succeeded for the 1.8.0 (or the deploy would never have been done):

The goal would be to add the failing case to the test harness or improve the current test to underline the bug you are reporting, so we could fix it with confidence

I cannot reproduce with the current test case:

$ docker run -ti --rm -v $(pwd):/$(pwd) -w $(pwd) --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.0
Unable to find image 'asciidoctor/docker-asciidoctor:1.8.0' locally
1.8.0: Pulling from asciidoctor/docker-asciidoctor
5843afab3874: Already exists 
28814869329d: Pull complete 
8b2a934ca54a: Pull complete 
d65b6e48ce97: Pull complete 
34b04e24c8a5: Pull complete 
4c3f5e13c98b: Pull complete 
76a3c5edf6fa: Pull complete 
389fbb2d561c: Pull complete 
Digest: sha256:2b88303c2f10f3d7a4823dfab5b34d990d91145e9440a37166f0c5549fab8c65
Status: Downloaded newer image for asciidoctor/docker-asciidoctor:1.8.0
bash-5.1# asciidoctor-pdf --version
Asciidoctor PDF 1.6.0 using Asciidoctor 2.0.15 [https://asciidoctor.org]
Runtime Environment (ruby 2.7.3p183 (2021-04-05 revision 6847ee089d) [x86_64-linux-musl]) (lc:UTF-8 fs:UTF-8 in:UTF-8 ex:UTF-8)
bash-5.1# asciidoctor-pdf -r asciidoctor-mathematical -D $(pwd) ./tests/fixtures/basic-example.adoc 
bash-5.1# ls -ltr *.pdf
-rw-r--r--    1 root     root         54833 Jul 20 09:04 basic-example.pdf

I assume there is a directive in your adoc file that triggers the error: if you can share the reproduction, we could add the directive(s) to the test case

p- commented

Hi @dduportal
Thanks for looking into this!

I'll have a look at our Adocs and report back, what might be the problem.

p- commented

Hi @dduportal

Unfortunately, I have no very good repro at the moment. For some reasons, I seem to get the error with an empty index.adoc too ๐Ÿค”

This should be the command that seems to lead to the error:
docker run -u 1741:20 -v /tmp[..]/asciidoc/projectSources/:/documents/ asciidoctor/docker-asciidoctor:1.8.0 asciidoctor-pdf --trace /documents/docs/src/developer-documentation/index.adoc

(I have to verify that this is the right command, since it's concated.)

With --trace the exception reads as follow:

/usr/lib/ruby/gems/2.7.0/gems/asciidoctor-pdf-1.6.0/lib/asciidoctor/pdf/converter.rb:3611:in `block (2 levels) in register_fonts': No such file or directory - notoserif-regular-subset.ttf not found in GEM_FONTS_DIR (Errno::ENOENT)
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-pdf-1.6.0/lib/asciidoctor/pdf/converter.rb:3603:in `each'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-pdf-1.6.0/lib/asciidoctor/pdf/converter.rb:3603:in `each_with_object'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-pdf-1.6.0/lib/asciidoctor/pdf/converter.rb:3603:in `block in register_fonts'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-pdf-1.6.0/lib/asciidoctor/pdf/converter.rb:3602:in `each'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-pdf-1.6.0/lib/asciidoctor/pdf/converter.rb:3602:in `register_fonts'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-pdf-1.6.0/lib/asciidoctor/pdf/converter.rb:328:in `init_pdf'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-pdf-1.6.0/lib/asciidoctor/pdf/converter.rb:161:in `convert_document'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-pdf-1.6.0/lib/asciidoctor/pdf/converter.rb:135:in `convert'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-2.0.15/lib/asciidoctor/document.rb:944:in `convert'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-2.0.15/lib/asciidoctor/convert.rb:117:in `convert'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-2.0.15/lib/asciidoctor/convert.rb:189:in `block in convert_file'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-2.0.15/lib/asciidoctor/convert.rb:189:in `open'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-2.0.15/lib/asciidoctor/convert.rb:189:in `convert_file'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-2.0.15/lib/asciidoctor/cli/invoker.rb:130:in `block in invoke!'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-2.0.15/lib/asciidoctor/cli/invoker.rb:113:in `each'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-2.0.15/lib/asciidoctor/cli/invoker.rb:113:in `invoke!'
        from /usr/lib/ruby/gems/2.7.0/gems/asciidoctor-pdf-1.6.0/bin/asciidoctor-pdf:27:in `<top (required)>'
        from /usr/bin/asciidoctor-pdf:23:in `load'
        from /usr/bin/asciidoctor-pdf:23:in `<main>'
p- commented

Ah I can reproduce the error like this:

docker run -ti --rm -v $(pwd):/$(pwd) -w $(pwd) --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.0

Then create an empty file inside the docker container (it's the same for files with content):

bash-5.1# touch index.adoc
bash-5.1# asciidoctor-pdf -r asciidoctor-mathematical -D $(pwd) ./index.adoc

Writes following:

No such file or directory - notoserif-regular-subset.ttf not found in GEM_FONTS_DIR

I'm not able to reproduce this problem in my own testing.

I am curious why you're using -D $(pwd) when calling asciidoctor-pdf. That's unnecessary given it's the directory you are already in.

It's possible that in your environment, the file isn't readable for some reason. You could try to put a debug statement at the line in question inside the container and see if there is a reason it cannot find the file.

That is weird, I cannot reproduce it at all. I suspect there is something related to the default user / UID of the shared volume.

I'll need the following element from you:

  • Output of docker info (to check if your Docker Engine is running in rootless mode or at least with usernamespacing enabled)
  • Result of docker run --rm --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.0 -c "whoami && id -u" (to check the current behavior of the image that should be run as root user with UID 0)
  • Result of docker run --rm -v $(pwd):/data --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.0 -c "ls -nd /data" (to check the current UID)
  • Result of docker run --rm --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.0 -c "touch index.adoc && asciidoctor-pdf ./index.adoc" (to check if we can reproduce the error without involving any additional parameter)
  • Result of docker run --rm -v $(pwd):$(pwd) --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.0 -c "touch index.adoc && asciidoctor-pdf ./index.adoc" (to check if we can reproduce the error with only 1 change at a time)
  • Result of docker run --rm -v $(pwd):$(pwd) -w $(pwd) --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.0 -c "touch index.adoc && asciidoctor-pdf ./index.adoc" (to check if we can reproduce the error with only 1 change at a time)

Actually, there is something even more fishy about this. You should never be seeing an error message that says "not found in GEM_FONTS_DIR". That value should be resolved to a concrete location. There has to be a reason it is not getting recognized.

Specifically, this line is not getting hit properly in your environment:

dir == 'GEM_FONTS_DIR' || dir.empty? ? ThemeLoader::FontsDir : dir
p- commented

Good news! (Sort of) I updated my local Docker before I saw @dduportal's new comment. My local Docker Engine/Server version is now 20.10.7. (Previously a recent Docker Engine 19.03.xy was in use.)

=> No issues with a recent Docker version.

Revert to Docker Desktop Community 2.5.0.1 (Docker Engine 19.03.13)

=> Now the issue occurs again.

So on another macOS-system I reverted back to following Docker version: Docker Desktop Community 2.5.0.1 (released on 2020-11-10)

@dduportal: here are the result for the non-working Docker-version:

docker info

Client:
 Debug Mode: false
 Plugins:
  scan: Docker Scan (Docker Inc., v0.3.4)

Server:
 Containers: 21
  Running: 3
  Paused: 0
  Stopped: 18
 Images: 54
 Server Version: 19.03.13
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 8fba4e9a7d01810a393d5d25a3621dc101981175
 runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd
 init version: fec3683
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 5.4.39-linuxkit
 Operating System: Docker Desktop
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 1.941GiB
 Name: docker-desktop
 ID: DMQ2:VBWD:P22M:QUGR:JAD5:6QP4:URYJ:W2UK:FDNY:XLZQ:QZW3:525Y
 Docker Root Dir: /var/lib/docker
 Debug Mode: true
  File Descriptors: 64
  Goroutines: 65
  System Time: 2021-07-20T11:20:51.319460365Z
  EventsListeners: 3
 HTTP Proxy: gateway.docker.internal:3128
 HTTPS Proxy: gateway.docker.internal:3129
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: true
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false
 Product License: Community Engine

docker run --rm --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.0 -c "whoami && id -u"

root
0

docker run --rm -v $(pwd):/data --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.0 -c "ls -nd /data"

drwxr-xr-x  121 0        0             3872 Jul 20 11:20 /data

docker run --rm --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.0 -c "touch index.adoc && asciidoctor-pdf ./index.adoc"

No such file or directory - notoserif-regular-subset.ttf not found in GEM_FONTS_DIR
  Use --trace for backtrace

docker run --rm -v $(pwd):$(pwd) --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.0 -c "touch index.adoc && asciidoctor-pdf ./index.adoc"

No such file or directory - notoserif-regular-subset.ttf not found in GEM_FONTS_DIR
  Use --trace for backtrace

docker run --rm -v $(pwd):$(pwd) -w $(pwd) --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.0 -c "touch index.adoc && asciidoctor-pdf ./index.adoc"

No such file or directory - notoserif-regular-subset.ttf not found in GEM_FONTS_DIR
  Use --trace for backtrace

I am curious why you're using -D $(pwd) when calling asciidoctor-pdf. That's unnecessary given it's the directory you are already in.

@mojavelinux Yeah, that was a copy and paste oversight. (The reference to asciidoctor-mathematical is also not necessary)

=> So it seems to have a connection to the Docker version (it seems not to work with Docker Engine 19.03.xy) ๐Ÿค”

Thanks for the additional informations. I was able to reproduce on a stock Docker 19.03 by using "Docker in Docker":

$ docker run --privileged --detach --name dind docker:19.03-dind
# ...
$ docker exec -ti dind sh
/ # docker run --rm --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.0 -c "touch index.a
doc && asciidoctor-pdf ./index.adoc"
Unable to find image 'asciidoctor/docker-asciidoctor:1.8.0' locally
1.8.0: Pulling from asciidoctor/docker-asciidoctor
5843afab3874: Pull complete 
28814869329d: Pull complete 
8b2a934ca54a: Pull complete 
d65b6e48ce97: Pull complete 
34b04e24c8a5: Pull complete 
4c3f5e13c98b: Pull complete 
76a3c5edf6fa: Pull complete 
389fbb2d561c: Pull complete 
Digest: sha256:2b88303c2f10f3d7a4823dfab5b34d990d91145e9440a37166f0c5549fab8c65
Status: Downloaded newer image for asciidoctor/docker-asciidoctor:1.8.0
No such file or directory - notoserif-regular-subset.ttf not found in GEM_FONTS_DIR
  Use --trace for backtrace

Gotta check what is wrong to see if we could have a fix, but I would prefer adding a documentation note.

p- commented

Hi @dduportal
Thanks for analyzing it!

My colleague thinks, that it might be connected to this runc issue:
opencontainers/runc#2151

So this issue seems to stem from the Alpine Linux 3.14.0 Update:
https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.14.0

Use of the faccessat2 syscall has been enabled in musl. Due to runc issue 2151, new system calls incorrectly returned EPERM instead of ENOSYS when invoked under a Docker with libseccomp predating their release.

I was able to reproduce on a stock Docker 19.03 by using "Docker in Docker":

Would you be able to check the line I referenced above and figure out why it is not being called? The program is clearly running, but for some reason it isn't executing that line. And I'm really curious to know why.

@mojavelinux it looks like that the issue is related to the use of Alpine. Let me try on Debian and with the older version of Alpine (3.13) as well

p- commented

@dduportal As per my comment #214 (comment), we are pretty sure that it's connected to an improvement in Alpine Linux 3.14.0.

Use of the faccessat2 syscall has been enabled in musl. Due to runc issue 2151, new system calls incorrectly returned EPERM instead of ENOSYS when invoked under a Docker with libseccomp predating their release. Therefore, Alpine Linux 3.14 requires one of the following:

  • runc v1.0.0-rc93
  • Docker 20.10.0 (which contains moby commit a181391) or greater, AND libseccomp 2.4.4

I think the easiest fix for the moment is to downgrade the base image of docker-asciidoctor to Alpine Linux 3.13. until everyone had a chance to update their Docker versions. Alpine Linux 3.13 is supported until 2022-11-01.

I want to make clear that the issue does not lay with docker-asciidoctor itself. But I think downgrading the image would lead to less issues for the moment ;)

@p- thanks for your diagnostic (and your colleague' ;) ). Your proposal sounds really good! Incoming PR :)

p- commented

@dduportal Thank you as well!

PS: I edited my comment above: every version of Alpine Linux that starts with 3.13. Should be ok. So you should be able to use 3.13.5 for example.

The latest image (release 1.9.0) should not have the bug anymore:

/ # docker run --rm --entrypoint=bash asciidoctor/docker-asciidoctor:1.9.0 -c "touch index.adoc && asciidoctor-pdf ./index.adoc"
Unable to find image 'asciidoctor/docker-asciidoctor:1.9.0' locally
1.9.0: Pulling from asciidoctor/docker-asciidoctor
540db60ca938: Pull complete 
4c307766f4ab: Pull complete 
c8d1ef386902: Pull complete 
eb6dd1c4c18e: Pull complete 
9f303379e54a: Pull complete 
50506f7936da: Pull complete 
220ca7927074: Pull complete 
ef49a045013d: Pull complete 
Digest: sha256:781f0d37a2d0d85997577794e298afd8bae588ea8ee07d56713e63a838776249
Status: Downloaded newer image for asciidoctor/docker-asciidoctor:1.9.0
/ # docker run --rm --entrypoint=bash asciidoctor/docker-asciidoctor:1.8.1 -c "touch index.adoc && asciidoctor-pdf ./index.adoc"
Unable to find image 'asciidoctor/docker-asciidoctor:1.8.1' locally
1.8.1: Pulling from asciidoctor/docker-asciidoctor
5843afab3874: Pull complete 
fd54b4ee913e: Pull complete 
bb037a87f9e3: Pull complete 
acdefd8081e6: Pull complete 
2ecf1a8f9727: Pull complete 
584f378a7f00: Pull complete 
62399cd1378c: Pull complete 
d9b426198514: Pull complete 
Digest: sha256:338fd558d6865f19647109700b6620a7462db99d37687f92d11fa2aa8eb9424f
Status: Downloaded newer image for asciidoctor/docker-asciidoctor:1.8.1
No such file or directory - notoserif-regular-subset.ttf not found in GEM_FONTS_DIR
  Use --trace for backtrace

Let us know if it is ok for you?

p- commented

@dduportal Yeah it seems to work. Thank you very much!