如何将额外的 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-cf
或gcr.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 映像中?的主要内容,如果未能解决你的问题,请参考以下文章
如何将缺少的依赖项添加到仅运行一次的 useEffect 挂钩?
sbt找不到ebean依赖项(一些未解析的依赖项有额外的属性)