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

Posted

技术标签:

【中文标题】如何将额外的 linux 依赖项添加到 spring-boot buildpack 映像中?【英文标题】:How to add extra linux dependencies into a spring-boot buildpack image? 【发布时间】:2020-10-10 13:21:58 【问题描述】:

我更新了我的 spring-boot 应用程序以使用 buildpacks 来创建我的 docker-image 而不是 dockerfile。我还在我的应用程序中使用 Apache POI,并且由于该更新,我在生成 xlsx 文件时出现错误。经过一番挖掘,我认为这是因为缺少 fontconfig 和/或 ttf-dejavu 包。但是如何在 dockerimage 中添加这些?使用 dockerfile 我只需添加类似

RUN apt-get update && apt-get install fontconfig ttf-dejavu

但是如何使用 buildpacks 实现相同的效果?

【问题讨论】:

【参考方案1】:

此答案假定“... spring-boot application to use buildpacks”是指使用 spring-boot:build-image maven 目标。

问题在于 maven 插件使用的默认构建器 (gcr.io/paketo-buildpacks/builder:base)。 Builder 负责配置 OS 镜像,“base”builder 不包含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 方法更容易。一些关于创建自定义构建器的文章:

https://buildpacks.io/docs/operator-guide/create-a-builder/ https://medium.com/@srinivasan.surprise/unpack-cloud-native-buildpacks-9959b601424b

【讨论】:

full-cf 构建器的镜像版本是每天构建的,所以基本上你每天都必须下载整个镜像(目前大约 550mb),当你开发你的应用程序时。最好(更舒适)使用更多“静态”版本,如full-cf-platform-api-latest。有所有构建器图像的列表:console.cloud.google.com/gcr/images/paketo-buildpacks/GLOBAL/…【参考方案2】:

正如 Michal 所述,使用更大的 paketobuildpacks/builder:full 构建器并不理想。此外,创建自定义构建器和堆栈将是一个巨大的开销 - 因为我们希望使用 Cloud Native Buildpacks 来让我们摆脱维护自己的 Dockerfile 的负担。并且创建我们自己的构建器/堆栈会带来比我们在编写 Dockerfile 之前更复杂的方式。

另一方面,由spring-boot-maven-plugin 或Spring Boot Gradle 插件创建的the need to install separate packages into the container images 很普遍。所以我想到了一种微创解决方案——这就是 (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

Create a new container image based on the one 我们将curl 安装到:

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

启动一个定义正确 ENTRYPOINT 的新容器以启动 Spring Boot 应用程序并切换回 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。

【讨论】:

赞成这个,因为它触及了问题的核心。它提供了一个相对简单且轻量级的解决方案,可以创建 Spring Boot 映像,而无需维护复杂的构建器堆栈或在我们的映像中引入大量膨胀。【参考方案3】:

我会稍微改进jonashackt的回答。

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

例如:

<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

【讨论】:

以上是关于如何将额外的 linux 依赖项添加到 spring-boot buildpack 映像中?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Google 视觉依赖项添加到我的 .aar?

如何将缺少的依赖项添加到仅运行一次的 useEffect 挂钩?

sbt找不到ebean依赖项(一些未解析的依赖项有额外的属性)

如何将 npm 依赖项添加为对等依赖项

如何将 gradle 库依赖项添加到 codenameone 项目

如何将 jquery-slider 添加到 browserify 中的依赖项列表中?