如何将额外的 linux 依赖项添加到 spring-boot buildpack 映像中?

How to add extra linux dependencies into a spring-boot buildpack image?

我更新了 spring-boot 应用程序以使用构建包创建我的 docker-image 而不是 docker 文件。我也在我的应用程序中使用 Apache POI,自从更新后我在生成 xlsx 文件时遇到错误。经过一番挖掘,我认为这是因为缺少 fontconfig and/or ttf-dejavu 包。但是如何将这些添加到 docker 图像中?对于 docker 文件,我只需添加类似

的内容
RUN apt-get update && apt-get install fontconfig ttf-dejavu

但是我如何使用 buildpack 实现同样的效果?

这个答案假设“... spring-boot 应用程序使用构建包”是指使用 spring-boot:build-image maven 目标。

问题出在 maven 插件使用的默认构建器 (gcr.io/paketo-buildpacks/builder:base) 上。 Builder 负责配置 OS 图像,“基础”构建器不包含 fontconfig 包。 .


启用 fontconfig 包的最简单方法是使用“完整”构建器(gcr.io/paketo-buildpacks/builder:full-cfgcr.io/paketo-buildpacks/builder:latest);例如,您可以通过以下方式之一执行此操作:

  • 通过在maven插件中指定builder配置参数,

    <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>
    
  • 或直接在 mvn 命令行中添加 -Dspring-boot.build-image.builder=gcr.io/paketo-buildpacks/builder:latest.

然而,这并不理想,因为完整的 OS 图像要大得多(“完整”图像大约为 1.45GB,而“基本”图像大约为 644MB - 在 docker 图像列表中观察到) ,用于启用 fontconfig.

的相当多的开销“只是”

一种更复杂的方法需要创建一个带有自定义 mixin 的自定义构建器,以便使用额外的包创建一个定制的“基础”图像。但我个人发现在这种情况下使用 dockerfile 方法更容易。关于创建自定义构建器的一些文章:

正如 Michal 所概述的,使用更大的 paketobuildpacks/builder:full 生成器并不理想。此外,创建自定义构建器和堆栈将是一个巨大的开销——因为我们想使用 Cloud Native Buildpacks 将我们从维护我们自己的 Dockerfile 的负担中解放出来。创建我们自己的 builder/stack 会带来比编写 Dockerfile.

之前更多的复杂性

另一方面,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)。假设我们的 mvn spring-boot:build-image(或 Gradle buildImage)命令生成了一个名为 my-app:0.0.1-SNAPSHOT:

的容器镜像

现在首先将 fontconfig ttf-dejavu 安装到映像中(为此我们需要 root 权限):

docker run --user="root" --entrypoint launcher my-app:0.0.1-SNAPSHOT "apt-get update && apt-get install fontconfig ttf-dejavu -y"

已停止容器的 Crab 容器 ID 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

我们将 curl 安装到:

docker commit 2ff7db32825f my-app-with-fontconfig-ttf

启动一个定义正确 ENTRYPOINT 的新容器以启动 Spring 启动应用并切换回 CNB 的标准 cnb 用户(并且不再使用 root 以避免潜在的安全问题风险):

docker run --rm -p 8080:8080 --user="cnb" --entrypoint /cnb/process/web my-app-with-fontconfig-ttf

有关更详细的背景信息see this so answer also

我会改进 jonashackt 的答案。

您可以创建新的 Dockerfile,而不是 运行 docker run,它将使用 Spring 启动插件生成的图像作为基础图像。

例如:

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <configuration>
    <image>
      <name>acme.com/artifact:boot</name>
    </image>
  </configuration>
</plugin>

然后在你的 Dockerfile

FROM acme.com/artifact:boot

USER root
RUN apt-get update && apt-get install -y fontconfig ttf-dejavu