I updated my spring-boot application to use buildpacks to create my docker-image instead of a dockerfile. I also use Apache POI in my application and since that update I get an error when generating an xlsx file. After some digging, I think it happens because the fontconfig
and/or ttf-dejavu
packages are missing. But how do I add these in the dockerimage? With a dockerfile I would just add something like
RUN apt-get update && apt-get install fontconfig ttf-dejavu
But how do I achieve the same with buildpacks?
This answer assumes that by "... spring-boot application to use buildpacks" you mean the use of the spring-boot:build-image
maven goal.
The issue lays with the default builder (gcr.io/paketo-buildpacks/builder:base
) used by the maven plugin. Builder is responsible for configuring the OS image, and the "base" builder doesn't include fontconfig
package. .
The easiest way to enable fontconfig
package is to use the "full" builder (gcr.io/paketo-buildpacks/builder:full-cf
or gcr.io/paketo-buildpacks/builder:latest
); you can do so for example in one of the following ways:
by specifying the builder configuration parameter in the maven plugin,
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.3.BUILD-SNAPSHOT</version>
<configuration>
<image>
<builder>gcr.io/paketo-buildpacks/builder:latest</builder>
</image>
</configuration>
</plugin>
</plugins>
</build>
</project>
or directly on your mvn
command line by adding -Dspring-boot.build-image.builder=gcr.io/paketo-buildpacks/builder:latest
.
However, this is not ideal because the full OS image is much larger (approx. 1.45GB for "full" vs. 644MB for "base" - observed in docker image listing), a fair bit of overhead "just" for enabling fontconfig
.
A more involved approach would require creating a custom builder with custom mixins, in order to create a tailored "base" image with the extra packages. But I personally found it easier to just use the dockerfile approach in this scenario. Some articles on creating a custom builder:
As Michal outlined, using the bigger paketobuildpacks/builder:full
builder isn't ideal. Also creating a custom builder & stack would be a huge overhead - since we want to use Cloud Native Buildpacks to free us from the burden of maintaining our own Dockerfile
. And creating our own builder/stack would bring in way more complexity then we had before writing the Dockerfile
.
On the other hand, the need to install separate packages into the container images created by the spring-boot-maven-plugin
or Spring Boot Gradle plugins is widespread. So I thought of a minimally invasive solution - and here it is (as derived from). Let's assume our mvn spring-boot:build-image
(or Gradle buildImage) command produced a container image called my-app:0.0.1-SNAPSHOT
:
Now first install fontconfig ttf-dejavu
into the image with (we need root priviledges for that):
docker run --user="root" --entrypoint launcher my-app:0.0.1-SNAPSHOT "apt-get update && apt-get install fontconfig ttf-dejavu -y"
Crab container id of the stopped container with docker ps -a
:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2ff7db32825f my-app:0.0.1-SNAPSHOT "launcher 'apt-get u…" 44 minutes ago Exited (0) 44 minutes ago reverent_swanson
Create a new container image based on the one we installed curl
into with:
docker commit 2ff7db32825f my-app-with-fontconfig-ttf
Fire up a new container defining the correct ENTRYPOINT
to start Spring Boot app & switching back to the CNB's standard cnb
user (and not using root anymore to avoid potential security risks):
docker run --rm -p 8080:8080 --user="cnb" --entrypoint /cnb/process/web my-app-with-fontconfig-ttf
For a more detailled background info see this so answer also.
I will improve answer from jonashackt a little bit.
Instead of running docker run
you can create new Dockerfile that will use image produced by Spring Boot plugin as a base image.
For example:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<name>acme.com/artifact:boot</name>
</image>
</configuration>
</plugin>
Then in your Dockerfile
FROM acme.com/artifact:boot
USER root
RUN apt-get update && apt-get install -y fontconfig ttf-dejavu
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With